diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-21 21:06:29 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-21 21:06:29 +0300 |
commit | f1bb2a307e9b125a8ee0be3728cb0d1baa21a3d4 (patch) | |
tree | 154817af5e3f1b134be08ef22d1926edf87ab74f | |
parent | ad1e4b8fb8104b642fa79ed34fd144bc2bed8a19 (diff) |
Add latest changes from gitlab-org/gitlab@master
27 files changed, 306 insertions, 198 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 65ee0959841..832e9afb6c1 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -1.67.0 +1.70.0 diff --git a/app/assets/javascripts/ide/components/jobs/stage.vue b/app/assets/javascripts/ide/components/jobs/stage.vue index 9ad9d4455b5..52ca61c06b0 100644 --- a/app/assets/javascripts/ide/components/jobs/stage.vue +++ b/app/assets/javascripts/ide/components/jobs/stage.vue @@ -58,6 +58,7 @@ export default { <template> <div class="ide-stage card prepend-top-default"> <div + ref="cardHeader" :class="{ 'border-bottom-0': stage.isCollapsed, }" @@ -79,7 +80,7 @@ export default { </div> <icon :name="collapseIcon" class="ide-stage-collapse-icon" /> </div> - <div v-show="!stage.isCollapsed" class="card-body"> + <div v-show="!stage.isCollapsed" ref="jobList" class="card-body"> <gl-loading-icon v-if="showLoadingIcon" /> <template v-else> <item v-for="job in stage.jobs" :key="job.id" :job="job" @clickViewLog="clickViewLog" /> diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js index f6722ff7bca..e08a67ec604 100644 --- a/app/assets/javascripts/search_autocomplete.js +++ b/app/assets/javascripts/search_autocomplete.js @@ -95,10 +95,10 @@ export class SearchAutocomplete { this.createAutocomplete(); } - this.searchInput.addClass('disabled'); this.saveTextLength(); this.bindEvents(); this.dropdownToggle.dropdown(); + this.searchInput.addClass('js-autocomplete-disabled'); } // Finds an element inside wrapper element @@ -338,7 +338,7 @@ export class SearchAutocomplete { if (!this.dropdown.hasClass('show')) { this.loadingSuggestions = false; this.dropdownToggle.dropdown('toggle'); - return this.searchInput.removeClass('disabled'); + return this.searchInput.removeClass('js-autocomplete-disabled'); } } @@ -432,8 +432,8 @@ export class SearchAutocomplete { } disableAutocomplete() { - if (!this.searchInput.hasClass('disabled') && this.dropdown.hasClass('show')) { - this.searchInput.addClass('disabled'); + if (!this.searchInput.hasClass('js-autocomplete-disabled') && this.dropdown.hasClass('show')) { + this.searchInput.addClass('js-autocomplete-disabled'); this.dropdown.removeClass('show').trigger('hidden.bs.dropdown'); this.restoreMenu(); } diff --git a/app/controllers/concerns/redirects_for_missing_path_on_tree.rb b/app/controllers/concerns/redirects_for_missing_path_on_tree.rb new file mode 100644 index 00000000000..085afbf3975 --- /dev/null +++ b/app/controllers/concerns/redirects_for_missing_path_on_tree.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module RedirectsForMissingPathOnTree + def redirect_to_tree_root_for_missing_path(project, ref, path) + redirect_to project_tree_path(project, ref), notice: missing_path_on_ref(path, ref) + end + + private + + def missing_path_on_ref(path, ref) + _('"%{path}" did not exist on "%{ref}"') % { path: truncate_path(path), ref: ref } + end + + def truncate_path(path) + path.reverse.truncate(60, separator: "/").reverse + end +end diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb index 9076bdb9f04..92655d593dd 100644 --- a/app/controllers/projects/blame_controller.rb +++ b/app/controllers/projects/blame_controller.rb @@ -3,6 +3,7 @@ # Controller for viewing a file's blame class Projects::BlameController < Projects::ApplicationController include ExtractsPath + include RedirectsForMissingPathOnTree before_action :require_non_empty_project before_action :assign_ref_vars @@ -11,7 +12,9 @@ class Projects::BlameController < Projects::ApplicationController def show @blob = @repository.blob_at(@commit.id, @path) - return render_404 unless @blob + unless @blob + return redirect_to_tree_root_for_missing_path(@project, @ref, @path) + end environment_params = @repository.branch_exists?(@ref) ? { ref: @ref } : { commit: @commit } @environment = EnvironmentsFinder.new(@project, current_user, environment_params).execute.last diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 7c3d43fb49a..205ec288ce9 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -7,6 +7,7 @@ class Projects::BlobController < Projects::ApplicationController include RendersBlob include NotesHelper include ActionView::Helpers::SanitizeHelper + include RedirectsForMissingPathOnTree prepend_before_action :authenticate_user!, only: [:edit] around_action :allow_gitaly_ref_name_caching, only: [:show] @@ -119,7 +120,7 @@ class Projects::BlobController < Projects::ApplicationController end end - return render_404 + return redirect_to_tree_root_for_missing_path(@project, @ref, @path) end end diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb index 050e2d1079b..1d914ab6011 100644 --- a/app/controllers/projects/jobs_controller.rb +++ b/app/controllers/projects/jobs_controller.rb @@ -12,7 +12,7 @@ class Projects::JobsController < Projects::ApplicationController before_action :authorize_use_build_terminal!, only: [:terminal, :terminal_websocket_authorize] before_action :verify_api_request!, only: :terminal_websocket_authorize before_action only: [:show] do - push_frontend_feature_flag(:job_log_json) + push_frontend_feature_flag(:job_log_json, project) end layout 'project' diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index 7509cc29a76..eec89afe354 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -5,6 +5,7 @@ class Projects::TreeController < Projects::ApplicationController include ExtractsPath include CreatesCommit include ActionView::Helpers::SanitizeHelper + include RedirectsForMissingPathOnTree around_action :allow_gitaly_ref_name_caching, only: [:show] @@ -19,12 +20,9 @@ class Projects::TreeController < Projects::ApplicationController if tree.entries.empty? if @repository.blob_at(@commit.id, @path) - return redirect_to( - project_blob_path(@project, - File.join(@ref, @path)) - ) + return redirect_to project_blob_path(@project, File.join(@ref, @path)) elsif @path.present? - return render_404 + return redirect_to_tree_root_for_missing_path(@project, @ref, @path) end end diff --git a/changelogs/unreleased/33533-go-to-root-if-no-path-on-branch.yml b/changelogs/unreleased/33533-go-to-root-if-no-path-on-branch.yml new file mode 100644 index 00000000000..c85faa9e7a2 --- /dev/null +++ b/changelogs/unreleased/33533-go-to-root-if-no-path-on-branch.yml @@ -0,0 +1,6 @@ +--- +title: When a user views a file's blame or blob and switches to a branch where the + current file does not exist, they will now be redirected to the root of the repository. +merge_request: 18169 +author: Jesse Hall @jessehall3 +type: changed diff --git a/changelogs/unreleased/pokstad1-gitaly-1-70-0.yml b/changelogs/unreleased/pokstad1-gitaly-1-70-0.yml new file mode 100644 index 00000000000..3ced037b74a --- /dev/null +++ b/changelogs/unreleased/pokstad1-gitaly-1-70-0.yml @@ -0,0 +1,5 @@ +--- +title: Bump Gitaly to 1.70.0 and remove cache invalidation feature flag +merge_request: 18766 +author: +type: other diff --git a/changelogs/unreleased/sh-use-template-project-id.yml b/changelogs/unreleased/sh-use-template-project-id.yml new file mode 100644 index 00000000000..7784007f536 --- /dev/null +++ b/changelogs/unreleased/sh-use-template-project-id.yml @@ -0,0 +1,5 @@ +--- +title: Fix incorrect selection of custom templates +merge_request: 17205 +author: +type: fixed diff --git a/db/post_migrate/20190809072552_set_self_monitoring_project_alerting_token.rb b/db/post_migrate/20190809072552_set_self_monitoring_project_alerting_token.rb index 0c4faebc548..d10887fb5d5 100644 --- a/db/post_migrate/20190809072552_set_self_monitoring_project_alerting_token.rb +++ b/db/post_migrate/20190809072552_set_self_monitoring_project_alerting_token.rb @@ -3,71 +3,17 @@ class SetSelfMonitoringProjectAlertingToken < ActiveRecord::Migration[5.2] DOWNTIME = false - module Migratable - module Alerting - class ProjectAlertingSetting < ApplicationRecord - self.table_name = 'project_alerting_settings' - - belongs_to :project - - validates :token, presence: true - - attr_encrypted :token, - mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, - algorithm: 'aes-256-gcm' - - before_validation :ensure_token - - private - - def ensure_token - self.token ||= generate_token - end - - def generate_token - SecureRandom.hex - end - end - end - - class Project < ApplicationRecord - has_one :alerting_setting, inverse_of: :project, class_name: 'Alerting::ProjectAlertingSetting' - end - - class ApplicationSetting < ApplicationRecord - self.table_name = 'application_settings' - - belongs_to :instance_administration_project, class_name: 'Project' - - def self.current_without_cache - last - end - end - end - - def setup_alertmanager_token(project) - return unless License.feature_available?(:prometheus_alerts) - - project.create_alerting_setting! - end - def up - Gitlab.ee do - project = Migratable::ApplicationSetting.current_without_cache&.instance_administration_project + # no-op + # Converted to no-op in https://gitlab.com/gitlab-org/gitlab/merge_requests/17049. - if project - setup_alertmanager_token(project) - end - end + # This migration has been made a no-op because the pre-requisite migration + # which creates the self-monitoring project has already been removed in + # https://gitlab.com/gitlab-org/gitlab/merge_requests/16864. As + # such, this migration would do nothing. end def down - Gitlab.ee do - Migratable::ApplicationSetting.current_without_cache - &.instance_administration_project - &.alerting_setting - &.destroy! - end + # no-op end end diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md index 0823c2e02b8..3a96f8204fc 100644 --- a/doc/development/testing_guide/flaky_tests.md +++ b/doc/development/testing_guide/flaky_tests.md @@ -83,6 +83,7 @@ This was originally implemented in: <https://gitlab.com/gitlab-org/gitlab-foss/m - In JS tests, shifting elements can cause Capybara to misclick when the element moves at the exact time Capybara sends the click - [Dropdowns rendering upward or downward due to window size and scroll position](https://gitlab.com/gitlab-org/gitlab/merge_requests/17660) - [Lazy loaded images can cause Capybara to misclick](https://gitlab.com/gitlab-org/gitlab/merge_requests/18713) +- [Triggering JS events before the event handlers are set up](https://gitlab.com/gitlab-org/gitlab/merge_requests/18742) #### Capybara viewport size related issues diff --git a/doc/user/project/integrations/generic_alerts.md b/doc/user/project/integrations/generic_alerts.md index ec43696fdee..b5f86c00eb3 100644 --- a/doc/user/project/integrations/generic_alerts.md +++ b/doc/user/project/integrations/generic_alerts.md @@ -1,6 +1,6 @@ # Generic alerts integration **(ULTIMATE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/13203) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.3. +> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/13203) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.4. GitLab can accept alerts from any source via a generic webhook receiver. When you set up the generic alerts integration, a unique endpoint will @@ -16,7 +16,7 @@ authored by the GitLab Alert Bot. To set up the generic alerts integration: 1. Navigate to **Settings > Integrations** in a project. -1. Click on **Alert endpoint**. +1. Click on **Alerts endpoint**. 1. Toggle the **Active** alert setting. The `URL` and `Authorization Key` for the webhook configuration can be found there. ## Customizing the payload diff --git a/lib/feature/gitaly.rb b/lib/feature/gitaly.rb index 81f8ba5c8c3..c23d7025d0f 100644 --- a/lib/feature/gitaly.rb +++ b/lib/feature/gitaly.rb @@ -7,7 +7,6 @@ class Feature # Server feature flags should use '_' to separate words. SERVER_FEATURE_FLAGS = %w[ - cache_invalidator inforef_uploadpack_cache get_all_lfs_pointers_go ].freeze diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 766b8c71dc5..6f66b51951d 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -62,6 +62,9 @@ msgstr "" msgid " or references (e.g. path/to/project!merge_request_id)" msgstr "" +msgid "\"%{path}\" did not exist on \"%{ref}\"" +msgstr "" + msgid "%d comment" msgid_plural "%d comments" msgstr[0] "" diff --git a/qa/qa/resource/runner.rb b/qa/qa/resource/runner.rb index 1be2429bc04..102c1ec83f5 100644 --- a/qa/qa/resource/runner.rb +++ b/qa/qa/resource/runner.rb @@ -36,7 +36,6 @@ module QA runner.tags = tags runner.image = image runner.config = config if config - runner.run_untagged = true runner.register! end end diff --git a/spec/controllers/concerns/redirects_for_missing_path_on_tree_spec.rb b/spec/controllers/concerns/redirects_for_missing_path_on_tree_spec.rb new file mode 100644 index 00000000000..903100ba93f --- /dev/null +++ b/spec/controllers/concerns/redirects_for_missing_path_on_tree_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe RedirectsForMissingPathOnTree, type: :controller do + controller(ActionController::Base) do + include Gitlab::Routing.url_helpers + include RedirectsForMissingPathOnTree + + def fake + redirect_to_tree_root_for_missing_path(Project.find(params[:project_id]), params[:ref], params[:file_path]) + end + end + + let(:project) { create(:project) } + + before do + routes.draw { get 'fake' => 'anonymous#fake' } + end + + describe '#redirect_to_root_path' do + it 'redirects to the tree path with a notice' do + long_file_path = ('a/b/' * 30) + 'foo.txt' + truncated_file_path = '...b/' + ('a/b/' * 12) + 'foo.txt' + expected_message = "\"#{truncated_file_path}\" did not exist on \"theref\"" + + get :fake, params: { project_id: project.id, ref: 'theref', file_path: long_file_path } + + expect(response).to redirect_to project_tree_path(project, 'theref') + expect(response.flash[:notice]).to eq(expected_message) + end + end +end diff --git a/spec/controllers/projects/blame_controller_spec.rb b/spec/controllers/projects/blame_controller_spec.rb index f901fd45604..dd7c0f45dc2 100644 --- a/spec/controllers/projects/blame_controller_spec.rb +++ b/spec/controllers/projects/blame_controller_spec.rb @@ -25,14 +25,25 @@ describe Projects::BlameController do }) end - context "valid file" do + context "valid branch, valid file" do let(:id) { 'master/files/ruby/popen.rb' } + it { is_expected.to respond_with(:success) } end - context "invalid file" do - let(:id) { 'master/files/ruby/missing_file.rb'} - it { expect(response).to have_gitlab_http_status(404) } + context "valid branch, invalid file" do + let(:id) { 'master/files/ruby/invalid-path.rb' } + + it 'redirects' do + expect(subject) + .to redirect_to("/#{project.full_path}/tree/master") + end + end + + context "invalid branch, valid file" do + let(:id) { 'invalid-branch/files/ruby/missing_file.rb'} + + it { is_expected.to respond_with(:not_found) } end end end diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb index 17964c78e8d..086ec9dfbcf 100644 --- a/spec/controllers/projects/blob_controller_spec.rb +++ b/spec/controllers/projects/blob_controller_spec.rb @@ -24,26 +24,34 @@ describe Projects::BlobController do context "valid branch, valid file" do let(:id) { 'master/README.md' } + it { is_expected.to respond_with(:success) } end context "valid branch, invalid file" do let(:id) { 'master/invalid-path.rb' } - it { is_expected.to respond_with(:not_found) } + + it 'redirects' do + expect(subject) + .to redirect_to("/#{project.full_path}/tree/master") + end end context "invalid branch, valid file" do let(:id) { 'invalid-branch/README.md' } + it { is_expected.to respond_with(:not_found) } end context "binary file" do let(:id) { 'binary-encoding/encoding/binary-1.bin' } + it { is_expected.to respond_with(:success) } end context "Markdown file" do let(:id) { 'master/README.md' } + it { is_expected.to respond_with(:success) } end end @@ -104,6 +112,7 @@ describe Projects::BlobController do context 'redirect to tree' do let(:id) { 'markdown/doc' } + it 'redirects' do expect(subject) .to redirect_to("/#{project.full_path}/tree/markdown/doc") diff --git a/spec/controllers/projects/tree_controller_spec.rb b/spec/controllers/projects/tree_controller_spec.rb index 7f7cabe3b0c..c0c11db5dd6 100644 --- a/spec/controllers/projects/tree_controller_spec.rb +++ b/spec/controllers/projects/tree_controller_spec.rb @@ -30,46 +30,61 @@ describe Projects::TreeController do context "valid branch, no path" do let(:id) { 'master' } + it { is_expected.to respond_with(:success) } end context "valid branch, valid path" do let(:id) { 'master/encoding/' } + it { is_expected.to respond_with(:success) } end context "valid branch, invalid path" do let(:id) { 'master/invalid-path/' } - it { is_expected.to respond_with(:not_found) } + + it 'redirects' do + expect(subject) + .to redirect_to("/#{project.full_path}/tree/master") + end end context "invalid branch, valid path" do let(:id) { 'invalid-branch/encoding/' } + it { is_expected.to respond_with(:not_found) } end context "valid empty branch, invalid path" do let(:id) { 'empty-branch/invalid-path/' } - it { is_expected.to respond_with(:not_found) } + + it 'redirects' do + expect(subject) + .to redirect_to("/#{project.full_path}/tree/empty-branch") + end end context "valid empty branch" do let(:id) { 'empty-branch' } + it { is_expected.to respond_with(:success) } end context "invalid SHA commit ID" do let(:id) { 'ff39438/.gitignore' } + it { is_expected.to respond_with(:not_found) } end context "valid SHA commit ID" do let(:id) { '6d39438' } + it { is_expected.to respond_with(:success) } end context "valid SHA commit ID with path" do let(:id) { '6d39438/.gitignore' } + it { expect(response).to have_gitlab_http_status(302) } end end @@ -108,6 +123,7 @@ describe Projects::TreeController do context 'redirect to blob' do let(:id) { 'master/README.md' } + it 'redirects' do redirect_url = "/#{project.full_path}/blob/master/README.md" expect(subject) diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb index 7e7c09e4a13..d386e489739 100644 --- a/spec/features/search/user_uses_header_search_field_spec.rb +++ b/spec/features/search/user_uses_header_search_field_spec.rb @@ -28,8 +28,7 @@ describe 'User uses header search field', :js do context 'when clicking the search field' do before do - page.find('#search').click - wait_for_all_requests + page.find('#search.js-autocomplete-disabled').click end it 'shows category search dropdown' do diff --git a/spec/finders/todos_finder_spec.rb b/spec/finders/todos_finder_spec.rb index 044e135fa0b..a4b076bc367 100644 --- a/spec/finders/todos_finder_spec.rb +++ b/spec/finders/todos_finder_spec.rb @@ -36,10 +36,18 @@ describe TodosFinder do expect(todos).to match_array([todo1, todo2]) end - it 'returns correct todos when filtered by a type' do - todos = finder.new(user, { type: 'Issue' }).execute + context 'when filtering by type' do + it 'returns correct todos when filtered by a type' do + todos = finder.new(user, { type: 'Issue' }).execute - expect(todos).to match_array([todo1]) + expect(todos).to match_array([todo1]) + end + + it 'returns the correct todos when filtering for multiple types' do + todos = finder.new(user, { type: %w[Issue MergeRequest] }).execute + + expect(todos).to match_array([todo1, todo2]) + end end context 'when filtering for actions' do @@ -53,12 +61,10 @@ describe TodosFinder do expect(todos).to match_array([todo2]) end - context 'multiple actions' do - it 'returns the expected todos' do - todos = finder.new(user, { action_id: [Todo::DIRECTLY_ADDRESSED, Todo::ASSIGNED] }).execute + it 'returns the expected todos when filtering for multiple action ids' do + todos = finder.new(user, { action_id: [Todo::DIRECTLY_ADDRESSED, Todo::ASSIGNED] }).execute - expect(todos).to match_array([todo2, todo1]) - end + expect(todos).to match_array([todo2, todo1]) end end @@ -69,12 +75,10 @@ describe TodosFinder do expect(todos).to match_array([todo2]) end - context 'multiple actions' do - it 'returns the expected todos' do - todos = finder.new(user, { action: [:directly_addressed, :assigned] }).execute + it 'returns the expected todos when filtering for multiple action names' do + todos = finder.new(user, { action: [:directly_addressed, :assigned] }).execute - expect(todos).to match_array([todo2, todo1]) - end + expect(todos).to match_array([todo2, todo1]) end end end diff --git a/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap new file mode 100644 index 00000000000..5d6c31f01d9 --- /dev/null +++ b/spec/frontend/ide/components/jobs/__snapshots__/stage_spec.js.snap @@ -0,0 +1,61 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`IDE pipeline stage renders stage details & icon 1`] = ` +<div + class="ide-stage card prepend-top-default" +> + <div + class="card-header" + > + <ciicon-stub + cssclasses="" + size="24" + status="[object Object]" + /> + + <strong + class="prepend-left-8 ide-stage-title" + data-container="body" + data-original-title="" + title="" + > + + build + + </strong> + + <div + class="append-right-8 prepend-left-4" + > + <span + class="badge badge-pill" + > + 4 + </span> + </div> + + <icon-stub + class="ide-stage-collapse-icon" + name="angle-down" + size="16" + /> + </div> + + <div + class="card-body" + > + <item-stub + job="[object Object]" + /> + <item-stub + job="[object Object]" + /> + <item-stub + job="[object Object]" + /> + <item-stub + job="[object Object]" + /> + </div> +</div> +`; diff --git a/spec/frontend/ide/components/jobs/stage_spec.js b/spec/frontend/ide/components/jobs/stage_spec.js new file mode 100644 index 00000000000..2e42ab26d27 --- /dev/null +++ b/spec/frontend/ide/components/jobs/stage_spec.js @@ -0,0 +1,86 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlLoadingIcon } from '@gitlab/ui'; +import Stage from '~/ide/components/jobs/stage.vue'; +import Item from '~/ide/components/jobs/item.vue'; +import { stages, jobs } from '../../mock_data'; + +describe('IDE pipeline stage', () => { + let wrapper; + const defaultProps = { + stage: { + ...stages[0], + id: 0, + dropdownPath: stages[0].dropdown_path, + jobs: [...jobs], + isLoading: false, + isCollapsed: false, + }, + }; + + const findHeader = () => wrapper.find({ ref: 'cardHeader' }); + const findJobList = () => wrapper.find({ ref: 'jobList' }); + + const createComponent = props => { + wrapper = shallowMount(Stage, { + propsData: { + ...defaultProps, + ...props, + }, + sync: false, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('emits fetch event when mounted', () => { + createComponent(); + expect(wrapper.emitted().fetch).toBeDefined(); + }); + + it('renders loading icon when no jobs and isLoading is true', () => { + createComponent({ + stage: { ...defaultProps.stage, isLoading: true, jobs: [] }, + }); + + expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); + }); + + it('emits toggleCollaped event with stage id when clicking header', () => { + const id = 5; + createComponent({ stage: { ...defaultProps.stage, id } }); + findHeader().trigger('click'); + expect(wrapper.emitted().toggleCollapsed[0][0]).toBe(id); + }); + + it('emits clickViewLog entity with job', () => { + const [job] = defaultProps.stage.jobs; + createComponent(); + wrapper + .findAll(Item) + .at(0) + .vm.$emit('clickViewLog', job); + expect(wrapper.emitted().clickViewLog[0][0]).toBe(job); + }); + + it('renders stage details & icon', () => { + createComponent(); + expect(wrapper.element).toMatchSnapshot(); + }); + + describe('when collapsed', () => { + beforeEach(() => { + createComponent({ stage: { ...defaultProps.stage, isCollapsed: true } }); + }); + + it('does not render job list', () => { + expect(findJobList().isVisible()).toBe(false); + }); + + it('sets border bottom class', () => { + expect(findHeader().classes('border-bottom-0')).toBe(true); + }); + }); +}); diff --git a/spec/javascripts/ide/components/jobs/stage_spec.js b/spec/javascripts/ide/components/jobs/stage_spec.js deleted file mode 100644 index fc3831f2d05..00000000000 --- a/spec/javascripts/ide/components/jobs/stage_spec.js +++ /dev/null @@ -1,95 +0,0 @@ -import Vue from 'vue'; -import Stage from '~/ide/components/jobs/stage.vue'; -import { stages, jobs } from '../../mock_data'; - -describe('IDE pipeline stage', () => { - const Component = Vue.extend(Stage); - let vm; - let stage; - - beforeEach(() => { - stage = { - ...stages[0], - id: 0, - dropdownPath: stages[0].dropdown_path, - jobs: [...jobs], - isLoading: false, - isCollapsed: false, - }; - - vm = new Component({ - propsData: { stage }, - }); - - spyOn(vm, '$emit'); - - vm.$mount(); - }); - - afterEach(() => { - vm.$destroy(); - }); - - it('emits fetch event when mounted', () => { - expect(vm.$emit).toHaveBeenCalledWith('fetch', vm.stage); - }); - - it('renders stages details', () => { - expect(vm.$el.textContent).toContain(vm.stage.name); - }); - - it('renders CI icon', () => { - expect(vm.$el.querySelector('.ic-status_failed')).not.toBe(null); - }); - - describe('collapsed', () => { - it('emits event when clicking header', done => { - vm.$el.querySelector('.card-header').click(); - - vm.$nextTick(() => { - expect(vm.$emit).toHaveBeenCalledWith('toggleCollapsed', vm.stage.id); - - done(); - }); - }); - - it('toggles collapse status when collapsed', done => { - vm.stage.isCollapsed = true; - - vm.$nextTick(() => { - expect(vm.$el.querySelector('.card-body').style.display).toBe('none'); - - done(); - }); - }); - - it('sets border bottom class when collapsed', done => { - vm.stage.isCollapsed = true; - - vm.$nextTick(() => { - expect(vm.$el.querySelector('.card-header').classList).toContain('border-bottom-0'); - - done(); - }); - }); - }); - - it('renders jobs count', () => { - expect(vm.$el.querySelector('.badge').textContent).toContain('4'); - }); - - it('renders loading icon when no jobs and isLoading is true', done => { - vm.stage.isLoading = true; - vm.stage.jobs = []; - - vm.$nextTick(() => { - expect(vm.$el.querySelector('.loading-container')).not.toBe(null); - - done(); - }); - }); - - it('renders list of jobs', () => { - expect(vm.$el.querySelectorAll('.ide-job-item').length).toBe(4); - }); -}); diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index e58f1b7d9dc..07e56619f40 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -843,8 +843,8 @@ describe 'Git HTTP requests' do get "/#{project.full_path}/blob/master/info/refs" end - it "returns not found" do - expect(response).to have_gitlab_http_status(:not_found) + it "redirects" do + expect(response).to have_gitlab_http_status(302) end end end |