From ad2bd11538a690b180d9966428ad02743bbf6ad9 Mon Sep 17 00:00:00 2001 From: Jamie Gordon Date: Fri, 6 Jul 2018 19:22:14 +0000 Subject: Fixes doc/development/architecture.md prod links. --- doc/development/architecture.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 6ca3e9e5a0a..66d8a4f2f6e 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -70,7 +70,7 @@ The add-on component gitlab-shell serves repositories over SSH. It manages the S Gitaly executes git operations from gitlab-shell and the GitLab web app, and provides an API to the GitLab web app to get attributes from git (e.g. title, branches, tags, other meta data), and to get blobs (e.g. diffs, commits, files). -You may also be interested in the [production architecture of GitLab.com](https://about.gitlab.com/handbook/infrastructure/production-architecture/). +You may also be interested in the [production architecture of GitLab.com](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/). ### Installation Folder Summary @@ -197,4 +197,4 @@ Note: It is recommended to log into the `git` user using `sudo -i -u git` or `su ## GitLab.com -We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/handbook/infrastructure/production-architecture/) but this is probably over the top unless you have millions of users. +We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/) but this is probably over the top unless you have millions of users. -- cgit v1.2.1 From abb50ff4710e264c0c700df88757ee3ab1cf7dfb Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Mon, 6 Aug 2018 16:02:52 -0300 Subject: Allow to delete group milestones --- .../pages/groups/milestones/show/index.js | 4 +- .../shared/components/delete_milestone_modal.vue | 6 +-- app/controllers/groups/milestones_controller.rb | 17 +++++++-- app/policies/group_policy.rb | 2 +- app/services/milestones/destroy_service.rb | 20 ++++++---- app/views/groups/milestones/index.html.haml | 2 +- app/views/projects/milestones/show.html.haml | 13 +------ .../shared/milestones/_delete_button.html.haml | 14 +++++++ app/views/shared/milestones/_milestone.html.haml | 2 +- app/views/shared/milestones/_top.html.haml | 5 ++- changelogs/unreleased/issue_36138.yml | 5 +++ config/routes/group.rb | 2 +- doc/api/group_milestones.md | 13 +++++++ lib/api/group_milestones.rb | 14 ++++++- lib/api/project_milestones.rb | 3 +- .../groups/milestones_controller_spec.rb | 11 ++++++ spec/factories/milestones.rb | 2 +- .../milestones/user_deletes_milestone_spec.rb | 44 ++++++++++++++++------ spec/policies/group_policy_spec.rb | 2 +- spec/requests/api/project_milestones_spec.rb | 13 ------- spec/services/milestones/destroy_service_spec.rb | 28 +++++++++++--- spec/support/api/milestones_shared_examples.rb | 18 +++++++++ 22 files changed, 172 insertions(+), 68 deletions(-) create mode 100644 app/views/shared/milestones/_delete_button.html.haml create mode 100644 changelogs/unreleased/issue_36138.yml diff --git a/app/assets/javascripts/pages/groups/milestones/show/index.js b/app/assets/javascripts/pages/groups/milestones/show/index.js index 74cc4ba42c1..ebaea5ef3dc 100644 --- a/app/assets/javascripts/pages/groups/milestones/show/index.js +++ b/app/assets/javascripts/pages/groups/milestones/show/index.js @@ -1,8 +1,10 @@ import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show'; +import initDeleteMilestoneModal from '~/pages/milestones/shared/delete_milestone_modal_init'; + import Milestone from '~/milestone'; document.addEventListener('DOMContentLoaded', () => { initMilestonesShow(); - + initDeleteMilestoneModal(); Milestone.initDeprecationMessage(); }); diff --git a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue b/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue index 4061c11ba8f..48668562f09 100644 --- a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue +++ b/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue @@ -40,8 +40,8 @@ if (this.issueCount === 0 && this.mergeRequestCount === 0) { return sprintf( s__(`Milestones| -You’re about to permanently delete the milestone %{milestoneTitle} from this project. -%{milestoneTitle} is not currently used in any issues or merge requests.`), +You’re about to permanently delete the milestone %{milestoneTitle}. +This milestone is not currently used in any issues or merge requests.`), { milestoneTitle, }, @@ -51,7 +51,7 @@ You’re about to permanently delete the milestone %{milestoneTitle} from this p return sprintf( s__(`Milestones| -You’re about to permanently delete the milestone %{milestoneTitle} from this project and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. +You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered.`), { milestoneTitle, diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 9bd51de7e97..6bdc0f79ef2 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -2,8 +2,8 @@ class Groups::MilestonesController < Groups::ApplicationController include MilestoneActions before_action :group_projects - before_action :milestone, only: [:edit, :show, :update, :merge_requests, :participants, :labels] - before_action :authorize_admin_milestones!, only: [:edit, :new, :create, :update] + before_action :milestone, only: [:edit, :show, :update, :merge_requests, :participants, :labels, :destroy] + before_action :authorize_admin_milestones!, only: [:edit, :new, :create, :update, :destroy] def index respond_to do |format| @@ -56,10 +56,21 @@ class Groups::MilestonesController < Groups::ApplicationController redirect_to milestone_path end + def destroy + return render_404 if @milestone.legacy_group_milestone? + + Milestones::DestroyService.new(group, current_user).execute(@milestone) + + respond_to do |format| + format.html { redirect_to group_milestones_path(group), status: :see_other } + format.js { head :ok } + end + end + private def authorize_admin_milestones! - return render_404 unless can?(current_user, :admin_milestones, group) + return render_404 unless can?(current_user, :admin_milestone, group) end def milestone_params diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index a8d7a05f509..333643865e9 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -53,7 +53,7 @@ class GroupPolicy < BasePolicy rule { has_access }.enable :read_namespace - rule { developer }.enable :admin_milestones + rule { developer }.enable :admin_milestone rule { reporter }.policy do enable :admin_label diff --git a/app/services/milestones/destroy_service.rb b/app/services/milestones/destroy_service.rb index 15c04525075..7cda802c120 100644 --- a/app/services/milestones/destroy_service.rb +++ b/app/services/milestones/destroy_service.rb @@ -3,8 +3,6 @@ module Milestones class DestroyService < Milestones::BaseService def execute(milestone) - return unless milestone.project_milestone? - Milestone.transaction do update_params = { milestone: nil } @@ -16,15 +14,21 @@ module Milestones MergeRequests::UpdateService.new(parent, current_user, update_params).execute(merge_request) end - event_service.destroy_milestone(milestone, current_user) - - Event.for_milestone_id(milestone.id).each do |event| - event.target_id = nil - event.save - end + log_destroy_event_for(milestone) milestone.destroy end end + + def log_destroy_event_for(milestone) + return if milestone.group_milestone? + + event_service.destroy_milestone(milestone, current_user) + + Event.for_milestone_id(milestone.id).each do |event| + event.target_id = nil + event.save + end + end end end diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index f5f621507b8..b6424df55cd 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -5,7 +5,7 @@ .nav-controls = render 'shared/milestones_sort_dropdown' - - if can?(current_user, :admin_milestones, @group) + - if can?(current_user, :admin_milestone, @group) = link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-new" .milestones diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 2a9e20c2caa..0a684f9016a 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -43,18 +43,7 @@ - else = link_to 'Reopen milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-nr btn-grouped" - %button.js-delete-milestone-button.btn.btn-grouped.btn-danger{ data: { toggle: 'modal', - target: '#delete-milestone-modal', - milestone_id: @milestone.id, - milestone_title: markdown_field(@milestone, :title), - milestone_url: project_milestone_path(@project, @milestone), - milestone_issue_count: @milestone.issues.count, - milestone_merge_request_count: @milestone.merge_requests.count }, - disabled: true } - = _('Delete') - = icon('spin spinner', class: 'js-loading-icon hidden' ) - - #delete-milestone-modal + = render 'shared/milestones/delete_button' %a.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ href: "#" } = icon('angle-double-left') diff --git a/app/views/shared/milestones/_delete_button.html.haml b/app/views/shared/milestones/_delete_button.html.haml new file mode 100644 index 00000000000..e236c24b088 --- /dev/null +++ b/app/views/shared/milestones/_delete_button.html.haml @@ -0,0 +1,14 @@ +- milestone_url = @milestone.project_milestone? ? project_milestone_path(@project, @milestone) : group_milestone_path(@group, @milestone) + +%button.js-delete-milestone-button.btn.btn-grouped.btn-danger{ data: { toggle: 'modal', + target: '#delete-milestone-modal', + milestone_id: @milestone.id, + milestone_title: markdown_field(@milestone, :title), + milestone_url: milestone_url, + milestone_issue_count: @milestone.issues.count, + milestone_merge_request_count: @milestone.merge_requests.count }, + disabled: true } + = _('Delete') + = icon('spin spinner', class: 'js-loading-icon hidden' ) + +#delete-milestone-modal diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml index c559945a9c9..b33bf5df707 100644 --- a/app/views/shared/milestones/_milestone.html.haml +++ b/app/views/shared/milestones/_milestone.html.haml @@ -49,7 +49,7 @@ - unless milestone.active? = link_to 'Reopen Milestone', project_milestone_path(@project, milestone, {state_event: :activate }), method: :put, class: "btn btn-grouped btn-reopen" - if @group - - if can?(current_user, :admin_milestones, @group) + - if can?(current_user, :admin_milestone, @group) - if milestone.closed? = link_to 'Reopen Milestone', group_milestone_route(milestone, {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen" - else diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml index 320e3788a0f..0499b04a482 100644 --- a/app/views/shared/milestones/_top.html.haml +++ b/app/views/shared/milestones/_top.html.haml @@ -23,7 +23,7 @@ = milestone_date_range(milestone) - if group .float-right - - if can?(current_user, :admin_milestones, group) + - if can?(current_user, :admin_milestone, group) - if milestone.group_milestone? = link_to edit_group_milestone_path(group, milestone), class: "btn btn btn-grouped" do Edit @@ -32,6 +32,9 @@ - else = link_to 'Reopen Milestone', group_milestone_route(milestone, {state_event: :activate }), method: :put, class: "btn btn-grouped btn-reopen" + - unless is_dynamic_milestone + = render 'shared/milestones/delete_button' + = render 'shared/milestones/deprecation_message' if is_dynamic_milestone .detail-page-description.milestone-detail diff --git a/changelogs/unreleased/issue_36138.yml b/changelogs/unreleased/issue_36138.yml new file mode 100644 index 00000000000..2fb2eea65f5 --- /dev/null +++ b/changelogs/unreleased/issue_36138.yml @@ -0,0 +1,5 @@ +--- +title: Allow to delete group milestones +merge_request: +author: +type: added diff --git a/config/routes/group.rb b/config/routes/group.rb index 25fbb38ba87..d7313e43786 100644 --- a/config/routes/group.rb +++ b/config/routes/group.rb @@ -37,7 +37,7 @@ constraints(::Constraints::GroupUrlConstrainer.new) do post :toggle_subscription, on: :member end - resources :milestones, constraints: { id: %r{[^/]+} }, only: [:index, :show, :edit, :update, :new, :create] do + resources :milestones, constraints: { id: %r{[^/]+} } do member do get :merge_requests get :participants diff --git a/doc/api/group_milestones.md b/doc/api/group_milestones.md index 152929b7614..e396f4411e6 100644 --- a/doc/api/group_milestones.md +++ b/doc/api/group_milestones.md @@ -96,6 +96,19 @@ Parameters: - `start_date` (optional) - The start date of the milestone - `state_event` (optional) - The state event of the milestone (close|activate) +## Delete group milestone + +Only for user with developer access to the group. + +``` +DELETE /groups/:id/milestones/:milestone_id +``` + +Parameters: + +- `id` (required) - The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user +- `milestone_id` (required) - The ID of the group's milestone + ## Get all issues assigned to a single milestone Gets all issues assigned to a single group milestone. diff --git a/lib/api/group_milestones.rb b/lib/api/group_milestones.rb index 93fa0b95857..4b4352c2b27 100644 --- a/lib/api/group_milestones.rb +++ b/lib/api/group_milestones.rb @@ -41,7 +41,7 @@ module API use :optional_params end post ":id/milestones" do - authorize! :admin_milestones, user_group + authorize! :admin_milestone, user_group create_milestone_for(user_group) end @@ -53,11 +53,21 @@ module API use :update_params end put ":id/milestones/:milestone_id" do - authorize! :admin_milestones, user_group + authorize! :admin_milestone, user_group update_milestone_for(user_group) end + desc 'Remove a project milestone' + delete ":id/milestones/:milestone_id" do + authorize! :admin_milestone, user_group + + milestone = user_group.milestones.find(params[:milestone_id]) + Milestones::DestroyService.new(user_group, current_user).execute(milestone) + + status(204) + end + desc 'Get all issues for a single group milestone' do success Entities::IssueBasic end diff --git a/lib/api/project_milestones.rb b/lib/api/project_milestones.rb index 306dc0e63d7..72cf32d7717 100644 --- a/lib/api/project_milestones.rb +++ b/lib/api/project_milestones.rb @@ -64,7 +64,8 @@ module API delete ":id/milestones/:milestone_id" do authorize! :admin_milestone, user_project - user_project.milestones.find(params[:milestone_id]).destroy + milestone = user_project.milestones.find(params[:milestone_id]) + Milestones::DestroyService.new(user_project, current_user).execute(milestone) status(204) end diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb index f7068546093..465f3499703 100644 --- a/spec/controllers/groups/milestones_controller_spec.rb +++ b/spec/controllers/groups/milestones_controller_spec.rb @@ -141,6 +141,17 @@ describe Groups::MilestonesController do end end + describe "#destroy" do + let(:milestone) { create(:milestone, group: group) } + + it "removes milestone" do + delete :destroy, group_id: group.to_param, id: milestone.iid, format: :js + + expect(response).to be_success + expect { Milestone.find(milestone.id) }.to raise_exception(ActiveRecord::RecordNotFound) + end + end + describe '#ensure_canonical_path' do before do sign_in(user) diff --git a/spec/factories/milestones.rb b/spec/factories/milestones.rb index f95632e7187..90cae4102f4 100644 --- a/spec/factories/milestones.rb +++ b/spec/factories/milestones.rb @@ -29,7 +29,7 @@ FactoryBot.define do milestone.project_id = evaluator.project_id elsif evaluator.parent id = evaluator.parent.id - evaluator.parent.is_a?(Group) ? board.group_id = id : evaluator.project_id = id + evaluator.parent.is_a?(Group) ? evaluator.group_id = id : evaluator.project_id = id else milestone.project = create(:project) end diff --git a/spec/features/milestones/user_deletes_milestone_spec.rb b/spec/features/milestones/user_deletes_milestone_spec.rb index 9d4a68239d3..a8c296b4cd2 100644 --- a/spec/features/milestones/user_deletes_milestone_spec.rb +++ b/spec/features/milestones/user_deletes_milestone_spec.rb @@ -1,26 +1,46 @@ require "rails_helper" describe "User deletes milestone", :js do - set(:user) { create(:user) } - set(:project) { create(:project) } - set(:milestone) { create(:milestone, project: project) } + let(:user) { create(:user) } + let(:group) { create(:group) } + let(:project) { create(:project, namespace: group) } before do - project.add_developer(user) sign_in(user) + end + + context "when milestone belongs to project" do + let!(:milestone) { create(:milestone, parent: project, title: "project milestone") } + + it "deletes milestone" do + project.add_developer(user) + visit(project_milestones_path(project)) + click_link(milestone.title) + click_button("Delete") + click_button("Delete milestone") + + expect(page).to have_content("No milestones to show") + + visit(activity_project_path(project)) - visit(project_milestones_path(project)) + expect(page).to have_content("#{user.name} destroyed milestone") + end end - it "deletes milestone" do - click_link(milestone.title) - click_button("Delete") - click_button("Delete milestone") + context "when milestone belongs to group" do + let!(:milestone_to_be_deleted) { create(:milestone, parent: group, title: "group milestone 1") } + let!(:milestone) { create(:milestone, parent: group, title: "group milestone 2") } - expect(page).to have_content("No milestones to show") + it "deletes milestone" do + group.add_developer(user) + visit(group_milestones_path(group)) - visit(activity_project_path(project)) + click_link(milestone_to_be_deleted.title) + click_button("Delete") + click_button("Delete milestone") - expect(page).to have_content("#{user.name} destroyed milestone") + expect(page).to have_content(milestone.title) + expect(page).not_to have_content(milestone_to_be_deleted) + end end end diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb index 35951251bc5..5ababe694c6 100644 --- a/spec/policies/group_policy_spec.rb +++ b/spec/policies/group_policy_spec.rb @@ -17,7 +17,7 @@ describe GroupPolicy do let(:reporter_permissions) { [:admin_label] } - let(:developer_permissions) { [:admin_milestones] } + let(:developer_permissions) { [:admin_milestone] } let(:maintainer_permissions) do [ diff --git a/spec/requests/api/project_milestones_spec.rb b/spec/requests/api/project_milestones_spec.rb index 6c05c166bd6..62613aa5938 100644 --- a/spec/requests/api/project_milestones_spec.rb +++ b/spec/requests/api/project_milestones_spec.rb @@ -39,19 +39,6 @@ describe API::ProjectMilestones do expect(response).to have_gitlab_http_status(404) end - - it "rejects a member with reporter access from deleting a milestone" do - delete api("/projects/#{project.id}/milestones/#{milestone.id}", reporter) - - expect(response).to have_gitlab_http_status(403) - end - - it 'deletes the milestone when the user has developer access to the project' do - delete api("/projects/#{project.id}/milestones/#{milestone.id}", user) - - expect(project.milestones.find_by_id(milestone.id)).to be_nil - expect(response).to have_gitlab_http_status(204) - end end describe 'PUT /projects/:id/milestones/:milestone_id to test observer on close' do diff --git a/spec/services/milestones/destroy_service_spec.rb b/spec/services/milestones/destroy_service_spec.rb index 6f3612501f4..8680e428517 100644 --- a/spec/services/milestones/destroy_service_spec.rb +++ b/spec/services/milestones/destroy_service_spec.rb @@ -4,8 +4,6 @@ describe Milestones::DestroyService do let(:user) { create(:user) } let(:project) { create(:project) } let(:milestone) { create(:milestone, title: 'Milestone v1.0', project: project) } - let!(:issue) { create(:issue, project: project, milestone: milestone) } - let!(:merge_request) { create(:merge_request, source_project: project, milestone: milestone) } before do project.add_maintainer(user) @@ -23,12 +21,23 @@ describe Milestones::DestroyService do end it 'deletes milestone id from issuables' do + issue = create(:issue, project: project, milestone: milestone) + merge_request = create(:merge_request, source_project: project, milestone: milestone) + service.execute(milestone) expect(issue.reload.milestone).to be_nil expect(merge_request.reload.milestone).to be_nil end + it 'logs destroy event' do + service.execute(milestone) + + event = Event.where(project_id: milestone.project_id, target_type: 'Milestone') + + expect(event.count).to eq(1) + end + context 'group milestones' do let(:group) { create(:group) } let(:group_milestone) { create(:milestone, group: group) } @@ -38,13 +47,20 @@ describe Milestones::DestroyService do group.add_developer(user) end - it { expect(service.execute(group_milestone)).to be_nil } + it { expect(service.execute(group_milestone)).to eq(group_milestone) } - it 'does not update milestone issuables' do - expect(MergeRequests::UpdateService).not_to receive(:new) - expect(Issues::UpdateService).not_to receive(:new) + it 'deletes milestone id from issuables' do + issue = create(:issue, project: project, milestone: group_milestone) + merge_request = create(:merge_request, source_project: project, milestone: group_milestone) service.execute(group_milestone) + + expect(issue.reload.milestone).to be_nil + expect(merge_request.reload.milestone).to be_nil + end + + it 'does not log destroy event' do + expect { service.execute(group_milestone) }.not_to change { Event.count } end end end diff --git a/spec/support/api/milestones_shared_examples.rb b/spec/support/api/milestones_shared_examples.rb index a15189db35f..8dbec499622 100644 --- a/spec/support/api/milestones_shared_examples.rb +++ b/spec/support/api/milestones_shared_examples.rb @@ -204,6 +204,24 @@ shared_examples_for 'group and project milestones' do |route_definition| end end + describe "DELETE #{route_definition}/:milestone_id" do + it "rejects a member with reporter access from deleting a milestone" do + reporter = create(:user) + milestone.parent.add_reporter(reporter) + + delete api(resource_route, reporter) + + expect(response).to have_gitlab_http_status(403) + end + + it 'deletes the milestone when the user has developer access to the project' do + delete api(resource_route, user) + + expect(project.milestones.find_by_id(milestone.id)).to be_nil + expect(response).to have_gitlab_http_status(204) + end + end + describe "GET #{route_definition}/:milestone_id/issues" do let(:issues_route) { "#{route}/#{milestone.id}/issues" } -- cgit v1.2.1 From 5e8f11e5fdb792f17d86cf9321537c5c56801a17 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 9 Aug 2018 12:05:13 +0100 Subject: Removes
sent from backend on tooltips in jobs When backend sends HTML it requires frontend to append it to the DOM causing XSS vulnerabilities. By removing the `
` we avoid those vulnerabilities --- .../components/graph/dropdown_job_component.vue | 3 +-- .../pipelines/components/graph/job_component.vue | 5 +---- app/views/ci/status/_dropdown_graph_badge.html.haml | 4 ++-- app/views/projects/jobs/_sidebar.html.haml | 2 +- lib/gitlab/ci/status/build/failed.rb | 2 +- spec/features/projects/jobs/user_browses_job_spec.rb | 4 ++-- .../features/projects/jobs/user_browses_jobs_spec.rb | 2 +- spec/features/projects/pipelines/pipeline_spec.rb | 4 ++-- spec/features/projects/pipelines/pipelines_spec.rb | 2 +- .../pipelines/graph/dropdown_job_component_spec.js | 8 -------- .../pipelines/graph/job_component_spec.js | 20 -------------------- spec/lib/gitlab/ci/status/build/factory_spec.rb | 2 +- .../gitlab/ci/status/build/failed_allowed_spec.rb | 4 ++-- spec/lib/gitlab/ci/status/build/failed_spec.rb | 4 ++-- spec/lib/gitlab/ci/status/build/retried_spec.rb | 2 +- spec/presenters/ci/build_presenter_spec.rb | 12 ++++++------ spec/serializers/build_serializer_spec.rb | 2 +- spec/serializers/job_entity_spec.rb | 4 ++-- 18 files changed, 27 insertions(+), 59 deletions(-) diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue index 8487c8036ee..2ad66f4fe86 100644 --- a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue @@ -1,6 +1,5 @@ + + diff --git a/spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js b/spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js new file mode 100644 index 00000000000..8465757deb6 --- /dev/null +++ b/spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js @@ -0,0 +1,162 @@ +import { mountComponentWithRender } from 'spec/helpers/vue_mount_component_helper'; +import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue'; + +const TEST_TITLE = 'lorem-ipsum-dolar-sit-amit-consectur-adipiscing-elit-sed-do'; +const CLASS_SHOW_TOOLTIP = 'js-show-tooltip'; +const STYLE_TRUNCATED = { + display: 'inline-block', + 'max-width': '20px', +}; +const STYLE_NORMAL = { + display: 'inline-block', + 'max-width': '1000px', +}; + +function mountTooltipOnTruncate(options, createChildren) { + return mountComponentWithRender(h => h(TooltipOnTruncate, options, createChildren(h)), '#app'); +} + +describe('TooltipOnTruncate component', () => { + let vm; + + beforeEach(() => { + const el = document.createElement('div'); + el.id = 'app'; + document.body.appendChild(el); + }); + + afterEach(() => { + vm.$destroy(); + }); + + describe('with default target', () => { + it('renders tooltip if truncated', done => { + const options = { + style: STYLE_TRUNCATED, + props: { + title: TEST_TITLE, + }, + }; + + vm = mountTooltipOnTruncate(options, () => [TEST_TITLE]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).toHaveClass(CLASS_SHOW_TOOLTIP); + expect(vm.$el).toHaveData('original-title', TEST_TITLE); + expect(vm.$el).toHaveData('placement', 'top'); + }) + .then(done) + .catch(done.fail); + }); + + it('does not render tooltip if normal', done => { + const options = { + style: STYLE_NORMAL, + props: { + title: TEST_TITLE, + }, + }; + + vm = mountTooltipOnTruncate(options, () => [TEST_TITLE]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).not.toHaveClass(CLASS_SHOW_TOOLTIP); + }) + .then(done) + .catch(done.fail); + }); + }); + + describe('with child target', () => { + it('renders tooltip if truncated', done => { + const options = { + style: STYLE_NORMAL, + props: { + title: TEST_TITLE, + truncateTarget: 'child', + }, + }; + + vm = mountTooltipOnTruncate(options, (h) => [ + h('a', { style: STYLE_TRUNCATED }, TEST_TITLE), + ]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).toHaveClass(CLASS_SHOW_TOOLTIP); + }) + .then(done) + .catch(done.fail); + }); + + it('does not render tooltip if normal', done => { + const options = { + props: { + title: TEST_TITLE, + truncateTarget: 'child', + }, + }; + + vm = mountTooltipOnTruncate(options, (h) => [ + h('a', { style: STYLE_NORMAL }, TEST_TITLE), + ]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).not.toHaveClass(CLASS_SHOW_TOOLTIP); + }) + .then(done) + .catch(done.fail); + }); + }); + + describe('with fn target', () => { + it('renders tooltip if truncated', done => { + const options = { + style: STYLE_NORMAL, + props: { + title: TEST_TITLE, + truncateTarget: (el) => el.childNodes[1], + }, + }; + + vm = mountTooltipOnTruncate(options, (h) => [ + h('a', { style: STYLE_NORMAL }, TEST_TITLE), + h('span', { style: STYLE_TRUNCATED }, TEST_TITLE), + ]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).toHaveClass(CLASS_SHOW_TOOLTIP); + }) + .then(done) + .catch(done.fail); + }); + }); + + describe('placement', () => { + it('sets data-placement when tooltip is rendered', done => { + const options = { + props: { + title: TEST_TITLE, + truncateTarget: 'child', + placement: 'bottom', + }, + }; + + vm = mountTooltipOnTruncate(options, (h) => [ + h('a', { style: STYLE_TRUNCATED }, TEST_TITLE), + ]); + + vm.$nextTick() + .then(() => { + expect(vm.$el).toHaveClass(CLASS_SHOW_TOOLTIP); + expect(vm.$el).toHaveData('placement', options.props.placement); + }) + .then(done) + .catch(done.fail); + }); + }); +}); -- cgit v1.2.1 From df567ddb40f2ee89e78a742417e0599c12d6f2a8 Mon Sep 17 00:00:00 2001 From: Paul Slaughter Date: Tue, 14 Aug 2018 13:09:28 -0500 Subject: Update MR header and pipeline to use .label-truncate with .label-branch Also: - Renamed .label-truncated to .label-truncate - Removed length checking in JS to let the CSS handle this - Improve IE11 compatibility of MR headers --- .../components/mr_widget_header.vue | 46 ++++++---------------- .../components/mr_widget_pipeline.vue | 15 +++++-- .../vue_merge_request_widget/mr_widget_options.vue | 1 + app/assets/stylesheets/pages/merge_requests.scss | 35 ++++++++-------- 4 files changed, 42 insertions(+), 55 deletions(-) diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue index a4c2289c590..1124cceeaa1 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue @@ -1,18 +1,16 @@
a, + > span { + display: inline-block; + max-width: 12.5em; + margin-bottom: -3px; + white-space: nowrap; + text-overflow: ellipsis; + line-height: 14px; + overflow: hidden; } } } @@ -582,7 +582,7 @@ @include media-breakpoint-down(md) { flex-direction: column; - align-items: flex-start; + align-items: stretch; .branch-actions { margin-top: 16px; @@ -593,6 +593,7 @@ .branch-actions { align-self: center; margin-left: $gl-padding; + white-space: nowrap; } } } @@ -918,7 +919,7 @@ flex: 1; flex-direction: row; - @include media-breakpoint-down(md) { + @include media-breakpoint-down(sm) { flex-direction: column; .stage-cell .stage-container { -- cgit v1.2.1 From 093690d0b77c37383ef6660c7c8231135260efc3 Mon Sep 17 00:00:00 2001 From: Paul Slaughter Date: Tue, 14 Aug 2018 08:57:16 -0500 Subject: Update MR deployment to use .label-truncate with .deploy-link --- .../components/deployment.vue | 22 +++++++++++++++------- app/assets/stylesheets/pages/merge_requests.scss | 3 +++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue index 21f21232596..d530ab2767b 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue @@ -1,5 +1,6 @@ + diff --git a/changelogs/unreleased/50101-env-block.yml b/changelogs/unreleased/50101-env-block.yml new file mode 100644 index 00000000000..11e603e7a79 --- /dev/null +++ b/changelogs/unreleased/50101-env-block.yml @@ -0,0 +1,5 @@ +--- +title: Creates vue component for environments information in job log view +merge_request: +author: +type: other diff --git a/locale/gitlab.pot b/locale/gitlab.pot index cbefb81dfa2..8883857f914 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -5492,6 +5492,9 @@ msgstr "" msgid "The collection of events added to the data gathered for that stage." msgstr "" +msgid "The deployment of this job to %{environmentLink} did not succeed." +msgstr "" + msgid "The fork relationship has been removed." msgstr "" @@ -5675,6 +5678,18 @@ msgstr "" msgid "This job has not started yet" msgstr "" +msgid "This job is an out-of-date deployment to %{environmentLink}." +msgstr "" + +msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}." +msgstr "" + +msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}." +msgstr "" + +msgid "This job is creating a deployment to %{environmentLink}." +msgstr "" + msgid "This job is in pending state and is waiting to be picked by a runner" msgstr "" @@ -5684,6 +5699,9 @@ msgstr "" msgid "This job is stuck, because you don't have any active runners that can run this job." msgstr "" +msgid "This job is the most recent deployment to %{link}." +msgstr "" + msgid "This job requires a manual action" msgstr "" diff --git a/spec/javascripts/jobs/components/environments_block_spec.js b/spec/javascripts/jobs/components/environments_block_spec.js new file mode 100644 index 00000000000..015c26be9fc --- /dev/null +++ b/spec/javascripts/jobs/components/environments_block_spec.js @@ -0,0 +1,137 @@ +import Vue from 'vue'; +import component from '~/jobs/components/environments_block.vue'; +import mountComponent from '../../helpers/vue_mount_component_helper'; + +describe('Environments block', () => { + const Component = Vue.extend(component); + let vm; + const icon = { + group: 'success', + icon: 'status_success', + label: 'passed', + text: 'passed', + tooltip: 'passed', + }; + const deployment = { + path: 'deployment', + name: 'deployment name', + }; + const environment = { + path: '/environment', + name: 'environment', + }; + + afterEach(() => { + vm.$destroy(); + }); + + describe('with latest deployment', () => { + it('renders info for most recent deployment', () => { + vm = mountComponent(Component, { + deploymentStatus: { + status: 'latest', + icon, + deployment, + environment, + }, + }); + + expect(vm.$el.textContent.trim()).toEqual( + 'This job is the most recent deployment to environment.', + ); + }); + }); + + describe('with out of date deployment', () => { + describe('with last deployment', () => { + it('renders info for out date and most recent', () => { + vm = mountComponent(Component, { + deploymentStatus: { + status: 'out_of_date', + icon, + deployment, + environment: Object.assign({}, environment, { + last_deployment: { name: 'deployment', path: 'last_deployment' }, + }), + }, + }); + + expect(vm.$el.textContent.trim()).toEqual( + 'This job is an out-of-date deployment to environment. View the most recent deployment deployment.', + ); + }); + }); + + describe('without last deployment', () => { + it('renders info about out of date deployment', () => { + vm = mountComponent(Component, { + deploymentStatus: { + status: 'out_of_date', + icon, + deployment: null, + environment, + }, + }); + + expect(vm.$el.textContent.trim()).toEqual( + 'This job is an out-of-date deployment to environment.', + ); + }); + }); + }); + + describe('with failed deployment', () => { + it('renders info about failed deployment', () => { + vm = mountComponent(Component, { + deploymentStatus: { + status: 'failed', + icon, + deployment: null, + environment, + }, + }); + + expect(vm.$el.textContent.trim()).toEqual( + 'The deployment of this job to environment did not succeed.', + ); + }); + }); + + describe('creating deployment', () => { + describe('with last deployment', () => { + it('renders info about creating deployment and overriding lastest deployment', () => { + vm = mountComponent(Component, { + deploymentStatus: { + status: 'creating', + icon, + deployment, + environment: Object.assign({}, environment, { + last_deployment: { name: 'deployment', path: 'last_deployment' }, + }), + }, + }); + + expect(vm.$el.textContent.trim()).toEqual( + 'This job is creating a deployment to environment and will overwrite the last deployment.', + ); + }); + }); + + describe('without last deployment', () => { + it('renders info about failed deployment', () => { + vm = mountComponent(Component, { + deploymentStatus: { + status: 'creating', + icon, + deployment: null, + environment, + }, + }); + + expect(vm.$el.textContent.trim()).toEqual( + 'This job is creating a deployment to environment.', + ); + }); + }); + }); +}); -- cgit v1.2.1 From 6bb08542579739ec5806a2dfe61c1f7c3c56a1f5 Mon Sep 17 00:00:00 2001 From: Paul Slaughter Date: Tue, 28 Aug 2018 08:06:40 +0000 Subject: Resolve "It's impossible to commit twice to the same branch" --- app/assets/javascripts/ide/stores/mutations.js | 8 +------ .../unreleased/50584-fix-ide-commit-twice.yml | 5 ++++ .../ide/stores/modules/commit/actions_spec.js | 28 ++++++++++++---------- 3 files changed, 21 insertions(+), 20 deletions(-) create mode 100644 changelogs/unreleased/50584-fix-ide-commit-twice.yml diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js index 56a8d9430c7..0347f803757 100644 --- a/app/assets/javascripts/ide/stores/mutations.js +++ b/app/assets/javascripts/ide/stores/mutations.js @@ -146,13 +146,7 @@ export default { staged: false, prevPath: '', moved: false, - lastCommit: Object.assign(state.entries[file.path].lastCommit, { - id: lastCommit.commit.id, - url: lastCommit.commit_path, - message: lastCommit.commit.message, - author: lastCommit.commit.author_name, - updatedAt: lastCommit.commit.authored_date, - }), + lastCommitSha: lastCommit.commit.id, }); if (prevPath) { diff --git a/changelogs/unreleased/50584-fix-ide-commit-twice.yml b/changelogs/unreleased/50584-fix-ide-commit-twice.yml new file mode 100644 index 00000000000..92b292cf4ab --- /dev/null +++ b/changelogs/unreleased/50584-fix-ide-commit-twice.yml @@ -0,0 +1,5 @@ +--- +title: Fix Web IDE unable to commit to same file twice +merge_request: 21372 +author: +type: fixed diff --git a/spec/javascripts/ide/stores/modules/commit/actions_spec.js b/spec/javascripts/ide/stores/modules/commit/actions_spec.js index 24a7d76f30b..06b8b452319 100644 --- a/spec/javascripts/ide/stores/modules/commit/actions_spec.js +++ b/spec/javascripts/ide/stores/modules/commit/actions_spec.js @@ -184,7 +184,7 @@ describe('IDE commit module actions', () => { branch, }) .then(() => { - expect(f.lastCommit.message).toBe(data.message); + expect(f.lastCommitSha).toBe(data.id); }) .then(done) .catch(done.fail); @@ -266,19 +266,21 @@ describe('IDE commit module actions', () => { }); describe('success', () => { + const COMMIT_RESPONSE = { + id: '123456', + short_id: '123', + message: 'test message', + committed_date: 'date', + stats: { + additions: '1', + deletions: '2', + }, + }; + beforeEach(() => { spyOn(service, 'commit').and.returnValue( Promise.resolve({ - data: { - id: '123456', - short_id: '123', - message: 'test message', - committed_date: 'date', - stats: { - additions: '1', - deletions: '2', - }, - }, + data: COMMIT_RESPONSE, }), ); }); @@ -352,8 +354,8 @@ describe('IDE commit module actions', () => { store .dispatch('commit/commitChanges') .then(() => { - expect(store.state.entries[store.state.openFiles[0].path].lastCommit.message).toBe( - 'test message', + expect(store.state.entries[store.state.openFiles[0].path].lastCommitSha).toBe( + COMMIT_RESPONSE.id, ); done(); -- cgit v1.2.1 From f0e12d84d2beb0a6bb7b0a51851d457b853ee603 Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Tue, 28 Aug 2018 08:12:53 +0000 Subject: Display default status emoji if only message is entered --- .../javascripts/pages/profiles/show/index.js | 32 +++++++++++++++++++--- .../unreleased/winh-default-status-emoji.yml | 5 ++++ spec/features/profiles/user_edit_profile_spec.rb | 10 +++++++ 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/winh-default-status-emoji.yml diff --git a/app/assets/javascripts/pages/profiles/show/index.js b/app/assets/javascripts/pages/profiles/show/index.js index 949219a0837..aea7b649c20 100644 --- a/app/assets/javascripts/pages/profiles/show/index.js +++ b/app/assets/javascripts/pages/profiles/show/index.js @@ -3,15 +3,22 @@ import createFlash from '~/flash'; import GfmAutoComplete from '~/gfm_auto_complete'; import EmojiMenu from './emoji_menu'; +const defaultStatusEmoji = 'speech_balloon'; + document.addEventListener('DOMContentLoaded', () => { const toggleEmojiMenuButtonSelector = '.js-toggle-emoji-menu'; const toggleEmojiMenuButton = document.querySelector(toggleEmojiMenuButtonSelector); const statusEmojiField = document.getElementById('js-status-emoji-field'); const statusMessageField = document.getElementById('js-status-message-field'); - const findNoEmojiPlaceholder = () => document.getElementById('js-no-emoji-placeholder'); + const toggleNoEmojiPlaceholder = (isVisible) => { + const placeholderElement = document.getElementById('js-no-emoji-placeholder'); + placeholderElement.classList.toggle('hidden', !isVisible); + }; + + const findStatusEmoji = () => toggleEmojiMenuButton.querySelector('gl-emoji'); const removeStatusEmoji = () => { - const statusEmoji = toggleEmojiMenuButton.querySelector('gl-emoji'); + const statusEmoji = findStatusEmoji(); if (statusEmoji) { statusEmoji.remove(); } @@ -19,7 +26,7 @@ document.addEventListener('DOMContentLoaded', () => { const selectEmojiCallback = (emoji, emojiTag) => { statusEmojiField.value = emoji; - findNoEmojiPlaceholder().classList.add('hidden'); + toggleNoEmojiPlaceholder(false); removeStatusEmoji(); toggleEmojiMenuButton.innerHTML += emojiTag; }; @@ -29,7 +36,7 @@ document.addEventListener('DOMContentLoaded', () => { statusEmojiField.value = ''; statusMessageField.value = ''; removeStatusEmoji(); - findNoEmojiPlaceholder().classList.remove('hidden'); + toggleNoEmojiPlaceholder(true); }); const emojiAutocomplete = new GfmAutoComplete(); @@ -44,6 +51,23 @@ document.addEventListener('DOMContentLoaded', () => { selectEmojiCallback, ); emojiMenu.bindEvents(); + + const defaultEmojiTag = Emoji.glEmojiTag(defaultStatusEmoji); + statusMessageField.addEventListener('input', () => { + const hasStatusMessage = statusMessageField.value.trim() !== ''; + const statusEmoji = findStatusEmoji(); + if (hasStatusMessage && statusEmoji) { + return; + } + + if (hasStatusMessage) { + toggleNoEmojiPlaceholder(false); + toggleEmojiMenuButton.innerHTML += defaultEmojiTag; + } else if (statusEmoji.dataset.name === defaultStatusEmoji) { + toggleNoEmojiPlaceholder(true); + removeStatusEmoji(); + } + }); }) .catch(() => createFlash('Failed to load emoji list!')); }); diff --git a/changelogs/unreleased/winh-default-status-emoji.yml b/changelogs/unreleased/winh-default-status-emoji.yml new file mode 100644 index 00000000000..00cca4db0a6 --- /dev/null +++ b/changelogs/unreleased/winh-default-status-emoji.yml @@ -0,0 +1,5 @@ +--- +title: Display default status emoji if only message is entered +merge_request: 21330 +author: +type: changed diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb index 9e60b4995bd..206a3a4fe9a 100644 --- a/spec/features/profiles/user_edit_profile_spec.rb +++ b/spec/features/profiles/user_edit_profile_spec.rb @@ -130,5 +130,15 @@ describe 'User edit profile' do visit user_path(user) expect(page).not_to have_selector '.cover-status' end + + it 'displays a default emoji if only message is entered' do + message = 'a status without emoji' + visit(profile_path) + fill_in 'js-status-message-field', with: message + + within('.js-toggle-emoji-menu') do + expect(page).to have_emoji('speech_balloon') + end + end end end -- cgit v1.2.1 From 4f3a2347beb600c50043e4549454e7349824d7d3 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Mon, 27 Aug 2018 09:57:24 +0100 Subject: Move package-and-qa to the test phase The problem is this: when each phase starts, it checks if all jobs in earlier phases are complete. package-and-qa is slow. As build is the first phase, if you trigger package-and-qa before the prepare phase is finished, the entire test phase will be blocked until package-and-qa completes, which isn't what we want. But equally, if build came _after_ test, then package-and-qa couldn't be started until the tests were finished. Putting it in the same stage as the tests means we can have our cake and eat it. --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 797a20ef16e..23d71675ae4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -131,7 +131,7 @@ stages: .single-script-job: &single-script-job image: ruby:2.4-alpine before_script: [] - stage: build + stage: test cache: {} dependencies: [] variables: &single-script-job-variables -- cgit v1.2.1 From 2e995901ab70b3df6b88f687aa2757a7cc019d1e Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Tue, 28 Aug 2018 10:25:07 +0000 Subject: Fix static analysis --- .flayignore | 1 + locale/gitlab.pot | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.flayignore b/.flayignore index 4b6f7ba693a..87411516a2a 100644 --- a/.flayignore +++ b/.flayignore @@ -6,6 +6,7 @@ app/controllers/projects/approvers_controller.rb app/controllers/projects/protected_branches/merge_access_levels_controller.rb app/controllers/projects/protected_branches/push_access_levels_controller.rb app/controllers/projects/protected_tags/create_access_levels_controller.rb +app/helpers/system_note_helper.rb app/policies/project_policy.rb app/models/concerns/relative_positioning.rb app/workers/stuck_merge_jobs_worker.rb diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 8883857f914..ce5d82d479b 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -3632,10 +3632,10 @@ msgstr "" msgid "Milestones" msgstr "" -msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} from this project and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered." +msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered." msgstr "" -msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} from this project. %{milestoneTitle} is not currently used in any issues or merge requests." +msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests." msgstr "" msgid "Milestones|Delete milestone" -- cgit v1.2.1 From 86a8955cf35b34b5a866d69f0766877e4e26e0f7 Mon Sep 17 00:00:00 2001 From: Jasper Maes Date: Sun, 26 Aug 2018 19:41:18 +0200 Subject: Rails 5: replace removed silence_stream --- changelogs/unreleased/rails5-silence-stream.yml | 5 +++++ lib/tasks/gettext.rake | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/rails5-silence-stream.yml diff --git a/changelogs/unreleased/rails5-silence-stream.yml b/changelogs/unreleased/rails5-silence-stream.yml new file mode 100644 index 00000000000..df4fd14a077 --- /dev/null +++ b/changelogs/unreleased/rails5-silence-stream.yml @@ -0,0 +1,5 @@ +--- +title: 'Rails 5: replace removed silence_stream' +merge_request: 21387 +author: Jasper Maes +type: other diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake index f431352b61e..a497d26312e 100644 --- a/lib/tasks/gettext.rake +++ b/lib/tasks/gettext.rake @@ -82,7 +82,7 @@ namespace :gettext do # `gettext:find` writes touches to temp files to `stderr` which would cause # `static-analysis` to report failures. We can ignore these. - silence_stream($stderr) do + silence_sdterr do Rake::Task['gettext:find'].invoke end @@ -118,4 +118,15 @@ namespace :gettext do end end end + + def silence_sdterr(&block) + old_stderr = $stderr.dup + $stderr.reopen(File::NULL) + $stderr.sync = true + + yield + ensure + $stderr.reopen(old_stderr) + old_stderr.close + end end -- cgit v1.2.1 From 0d01ac51419cd429bd0ca02e42085e73db9ba713 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Tue, 28 Aug 2018 14:39:17 +0100 Subject: Include rich_text in diff cache keys Previously, this wasn't needed: text was normally set to the highlighted contents anyway. Now, it is: we store different things in text and rich_text. This caused https://gitlab.com/gitlab-com/production/issues/439. --- lib/gitlab/diff/line.rb | 7 ++++--- spec/lib/gitlab/conflict/file_spec.rb | 4 ---- spec/lib/gitlab/diff/line_spec.rb | 12 ++++++++++++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb index 633985d5caa..1ab6df0b6ae 100644 --- a/lib/gitlab/diff/line.rb +++ b/lib/gitlab/diff/line.rb @@ -1,16 +1,17 @@ module Gitlab module Diff class Line - SERIALIZE_KEYS = %i(line_code text type index old_pos new_pos).freeze + SERIALIZE_KEYS = %i(line_code rich_text text type index old_pos new_pos).freeze attr_reader :line_code, :type, :index, :old_pos, :new_pos attr_writer :rich_text attr_accessor :text - def initialize(text, type, index, old_pos, new_pos, parent_file: nil, line_code: nil) + def initialize(text, type, index, old_pos, new_pos, parent_file: nil, line_code: nil, rich_text: nil) @text, @type, @index = text, type, index @old_pos, @new_pos = old_pos, new_pos @parent_file = parent_file + @rich_text = rich_text # When line code is not provided from cache store we build it # using the parent_file(Diff::File or Conflict::File). @@ -18,7 +19,7 @@ module Gitlab end def self.init_from_hash(hash) - new(hash[:text], hash[:type], hash[:index], hash[:old_pos], hash[:new_pos], line_code: hash[:line_code]) + new(hash[:text], hash[:type], hash[:index], hash[:old_pos], hash[:new_pos], line_code: hash[:line_code], rich_text: hash[:rich_text]) end def to_hash diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb index 5b343920429..9095ffbfd52 100644 --- a/spec/lib/gitlab/conflict/file_spec.rb +++ b/spec/lib/gitlab/conflict/file_spec.rb @@ -69,10 +69,6 @@ describe Gitlab::Conflict::File do CGI.unescapeHTML(ActionView::Base.full_sanitizer.sanitize(html)).delete("\n") end - it 'modifies the existing lines' do - expect { conflict_file.highlight_lines! }.to change { conflict_file.lines.map(&:instance_variables) } - end - it 'is called implicitly when rich_text is accessed on a line' do expect(conflict_file).to receive(:highlight_lines!).once.and_call_original diff --git a/spec/lib/gitlab/diff/line_spec.rb b/spec/lib/gitlab/diff/line_spec.rb index e9d382d59c6..76d411973c7 100644 --- a/spec/lib/gitlab/diff/line_spec.rb +++ b/spec/lib/gitlab/diff/line_spec.rb @@ -1,4 +1,16 @@ describe Gitlab::Diff::Line do + describe '.init_from_hash' do + it 'round-trips correctly with to_hash' do + line = described_class.new('', 'match', 0, 0, 1, + parent_file: double(:file), + line_code: double(:line_code), + rich_text: '<input>') + + expect(described_class.init_from_hash(line.to_hash).to_hash) + .to eq(line.to_hash) + end + end + context "when setting rich text" do it 'escapes any HTML special characters in the diff chunk header' do subject = described_class.new("", "", 0, 0, 0) -- cgit v1.2.1 From 520fcaab1c202d4cfe0703c324f46e821d93e1ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 3 Aug 2018 13:25:14 +0200 Subject: Allow to pass --tag to bin/qa run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- qa/qa/scenario/template.rb | 8 ++++++-- qa/qa/scenario/test/instance.rb | 7 ++++++- qa/spec/runtime/env_spec.rb | 4 ++++ qa/spec/scenario/test/instance/all_spec.rb | 8 +++++++- qa/spec/scenario/test/instance/smoke_spec.rb | 2 +- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/qa/qa/scenario/template.rb b/qa/qa/scenario/template.rb index 66eb86f25c8..a87d925ce32 100644 --- a/qa/qa/scenario/template.rb +++ b/qa/qa/scenario/template.rb @@ -21,14 +21,18 @@ module QA def perform(address, *rspec_options) Runtime::Scenario.define(:gitlab_address, address) + ## + # Perform before hooks, which are different for CE and EE + # + Runtime::Release.perform_before_hooks + Specs::Runner.perform do |specs| specs.tty = true - specs.tags = self.class.focus specs.options = if rspec_options.any? rspec_options else - ::File.expand_path('../specs/features', __dir__) + ['--tag', self.class.focus.join(','), '--', ::File.expand_path('../specs/features', __dir__)] end end end diff --git a/qa/qa/scenario/test/instance.rb b/qa/qa/scenario/test/instance.rb index 2117a610efb..e41c742376a 100644 --- a/qa/qa/scenario/test/instance.rb +++ b/qa/qa/scenario/test/instance.rb @@ -20,13 +20,18 @@ module QA def self.do_perform(address, *rspec_options) Runtime::Scenario.define(:gitlab_address, address) + ## + # Perform before hooks, which are different for CE and EE + # + Runtime::Release.perform_before_hooks + Specs::Runner.perform do |specs| specs.tty = true specs.options = if rspec_options.any? rspec_options else - ::File.expand_path('../../specs/features', __dir__) + ['--tag', self.class.focus.join(','), '--', ::File.expand_path('../../specs/features', __dir__)] end end end diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb index ccc0b906845..5493a33cd2a 100644 --- a/qa/spec/runtime/env_spec.rb +++ b/qa/spec/runtime/env_spec.rb @@ -104,6 +104,8 @@ describe QA::Runtime::Env do describe '.github_access_token' do it 'returns "" if GITHUB_ACCESS_TOKEN is not defined' do + stub_env('GITHUB_ACCESS_TOKEN', nil) + expect(described_class.github_access_token).to eq('') end @@ -115,6 +117,8 @@ describe QA::Runtime::Env do describe '.require_github_access_token!' do it 'raises ArgumentError if GITHUB_ACCESS_TOKEN is not defined' do + stub_env('GITHUB_ACCESS_TOKEN', nil) + expect { described_class.require_github_access_token! }.to raise_error(ArgumentError) end diff --git a/qa/spec/scenario/test/instance/all_spec.rb b/qa/spec/scenario/test/instance/all_spec.rb index 423527e938e..1d96352550b 100644 --- a/qa/spec/scenario/test/instance/all_spec.rb +++ b/qa/spec/scenario/test/instance/all_spec.rb @@ -1,4 +1,10 @@ describe QA::Scenario::Test::Instance::All do + subject do + Class.new(described_class) do + tags :rspec, :foo + end + end + context '#perform' do let(:arguments) { spy('Runtime::Scenario') } let(:release) { spy('Runtime::Release') } @@ -24,7 +30,7 @@ describe QA::Scenario::Test::Instance::All do subject.perform("test") expect(runner).to have_received(:options=) - .with(::File.expand_path('../../../../qa/specs/features', __dir__)) + .with(['--tag', 'rspec,foo', '--', ::File.expand_path('../../../../qa/specs/features', __dir__)]) end end diff --git a/qa/spec/scenario/test/instance/smoke_spec.rb b/qa/spec/scenario/test/instance/smoke_spec.rb index e79d19e8212..386eefae930 100644 --- a/qa/spec/scenario/test/instance/smoke_spec.rb +++ b/qa/spec/scenario/test/instance/smoke_spec.rb @@ -30,7 +30,7 @@ describe QA::Scenario::Test::Instance::Smoke do subject.perform("test") expect(runner).to have_received(:options=) - .with(::File.expand_path('../../../../qa/specs/features', __dir__)) + .with(['--tag', 'smoke', '--', ::File.expand_path('../../../../qa/specs/features', __dir__)]) end end -- cgit v1.2.1 From 7cd3fbb66f5b289f16cb6ba619fe6372285d316e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 7 Aug 2018 16:54:16 +0200 Subject: Reorganize QA scenarios based on the DevOps cycle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- qa/qa/specs/features/api/1_manage/.gitkeep | 0 qa/qa/specs/features/api/1_manage/users_spec.rb | 41 ++++++++ qa/qa/specs/features/api/2_plan/.gitkeep | 0 .../features/api/3_create/repository/files_spec.rb | 61 ++++++++++++ qa/qa/specs/features/api/4_verify/.gitkeep | 0 qa/qa/specs/features/api/5_package/.gitkeep | 0 qa/qa/specs/features/api/6_release/.gitkeep | 0 qa/qa/specs/features/api/7_configure/.gitkeep | 0 qa/qa/specs/features/api/basics_spec.rb | 61 ------------ qa/qa/specs/features/api/users_spec.rb | 41 -------- .../browser_ui/1_manage/login/log_in_spec.rb | 17 ++++ .../login/log_into_gitlab_via_ldap_spec.rb | 19 ++++ .../login/log_into_mattermost_via_gitlab_spec.rb | 17 ++++ .../1_manage/project/create_project_spec.rb | 22 +++++ .../1_manage/project/import_github_repo_spec.rb | 106 +++++++++++++++++++++ .../1_manage/project/view_project_activity_spec.rb | 20 ++++ .../browser_ui/2_plan/issue/create_issue_spec.rb | 18 ++++ .../merge_request/create_merge_request_spec.rb | 53 +++++++++++ .../merge_merge_request_from_fork_spec.rb | 21 ++++ .../merge_request/rebase_merge_request_spec.rb | 39 ++++++++ .../merge_request/squash_merge_request_spec.rb | 50 ++++++++++ .../browser_ui/3_create/repository/clone_spec.rb | 58 +++++++++++ .../create_edit_delete_file_via_web_spec.rb | 54 +++++++++++ .../3_create/repository/push_over_http_spec.rb | 21 ++++ .../repository/push_protected_branch_spec.rb | 66 +++++++++++++ .../wiki/create_edit_clone_push_wiki_spec.rb | 45 +++++++++ .../pipeline/create_and_process_pipeline_spec.rb | 102 ++++++++++++++++++++ .../4_verify/runner/register_runner_spec.rb | 32 +++++++ .../secret_variable/add_secret_variable_spec.rb | 24 +++++ qa/qa/specs/features/browser_ui/5_package/.gitkeep | 0 .../6_release/deploy_key/add_deploy_key_spec.rb | 19 ++++ .../deploy_key/clone_using_deploy_key_spec.rb | 105 ++++++++++++++++++++ .../create_project_with_auto_devops_spec.rb | 64 +++++++++++++ .../create_group_with_mattermost_team_spec.rb | 17 ++++ qa/qa/specs/features/login/ldap_spec.rb | 19 ---- .../specs/features/mattermost/group_create_spec.rb | 17 ---- qa/qa/specs/features/mattermost/login_spec.rb | 17 ---- qa/qa/specs/features/merge_request/create_spec.rb | 53 ----------- qa/qa/specs/features/merge_request/rebase_spec.rb | 39 -------- qa/qa/specs/features/merge_request/squash_spec.rb | 50 ---------- qa/qa/specs/features/project/activity_spec.rb | 20 ---- .../specs/features/project/add_deploy_key_spec.rb | 19 ---- .../features/project/add_secret_variable_spec.rb | 24 ----- qa/qa/specs/features/project/auto_devops_spec.rb | 64 ------------- qa/qa/specs/features/project/create_issue_spec.rb | 18 ---- qa/qa/specs/features/project/create_spec.rb | 22 ----- .../features/project/deploy_key_clone_spec.rb | 105 -------------------- qa/qa/specs/features/project/file_spec.rb | 54 ----------- qa/qa/specs/features/project/fork_project_spec.rb | 21 ---- .../features/project/import_from_github_spec.rb | 106 --------------------- qa/qa/specs/features/project/pipelines_spec.rb | 102 -------------------- qa/qa/specs/features/project/wikis_spec.rb | 45 --------- qa/qa/specs/features/repository/clone_spec.rb | 58 ----------- .../features/repository/protected_branches_spec.rb | 66 ------------- qa/qa/specs/features/repository/push_spec.rb | 21 ---- 55 files changed, 1091 insertions(+), 1042 deletions(-) create mode 100644 qa/qa/specs/features/api/1_manage/.gitkeep create mode 100644 qa/qa/specs/features/api/1_manage/users_spec.rb create mode 100644 qa/qa/specs/features/api/2_plan/.gitkeep create mode 100644 qa/qa/specs/features/api/3_create/repository/files_spec.rb create mode 100644 qa/qa/specs/features/api/4_verify/.gitkeep create mode 100644 qa/qa/specs/features/api/5_package/.gitkeep create mode 100644 qa/qa/specs/features/api/6_release/.gitkeep create mode 100644 qa/qa/specs/features/api/7_configure/.gitkeep delete mode 100644 qa/qa/specs/features/api/basics_spec.rb delete mode 100644 qa/qa/specs/features/api/users_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/5_package/.gitkeep create mode 100644 qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb delete mode 100644 qa/qa/specs/features/login/ldap_spec.rb delete mode 100644 qa/qa/specs/features/mattermost/group_create_spec.rb delete mode 100644 qa/qa/specs/features/mattermost/login_spec.rb delete mode 100644 qa/qa/specs/features/merge_request/create_spec.rb delete mode 100644 qa/qa/specs/features/merge_request/rebase_spec.rb delete mode 100644 qa/qa/specs/features/merge_request/squash_spec.rb delete mode 100644 qa/qa/specs/features/project/activity_spec.rb delete mode 100644 qa/qa/specs/features/project/add_deploy_key_spec.rb delete mode 100644 qa/qa/specs/features/project/add_secret_variable_spec.rb delete mode 100644 qa/qa/specs/features/project/auto_devops_spec.rb delete mode 100644 qa/qa/specs/features/project/create_issue_spec.rb delete mode 100644 qa/qa/specs/features/project/create_spec.rb delete mode 100644 qa/qa/specs/features/project/deploy_key_clone_spec.rb delete mode 100644 qa/qa/specs/features/project/file_spec.rb delete mode 100644 qa/qa/specs/features/project/fork_project_spec.rb delete mode 100644 qa/qa/specs/features/project/import_from_github_spec.rb delete mode 100644 qa/qa/specs/features/project/pipelines_spec.rb delete mode 100644 qa/qa/specs/features/project/wikis_spec.rb delete mode 100644 qa/qa/specs/features/repository/clone_spec.rb delete mode 100644 qa/qa/specs/features/repository/protected_branches_spec.rb delete mode 100644 qa/qa/specs/features/repository/push_spec.rb diff --git a/qa/qa/specs/features/api/1_manage/.gitkeep b/qa/qa/specs/features/api/1_manage/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/qa/qa/specs/features/api/1_manage/users_spec.rb b/qa/qa/specs/features/api/1_manage/users_spec.rb new file mode 100644 index 00000000000..3d25cca1e59 --- /dev/null +++ b/qa/qa/specs/features/api/1_manage/users_spec.rb @@ -0,0 +1,41 @@ +module QA + describe 'API users' do + before(:context) do + @api_client = Runtime::API::Client.new(:gitlab) + end + + context 'when authenticated' do + let(:request) { Runtime::API::Request.new(@api_client, '/users') } + + it 'get list of users' do + get request.url + + expect_status(200) + end + + it 'submit request with a valid user name' do + get request.url, { params: { username: Runtime::User.username } } + + expect_status(200) + expect(json_body).to contain_exactly( + a_hash_including(username: Runtime::User.username) + ) + end + + it 'submit request with an invalid user name' do + get request.url, { params: { username: SecureRandom.hex(10) } } + + expect_status(200) + expect(json_body).to eq([]) + end + end + + it 'submit request with an invalid token' do + request = Runtime::API::Request.new(@api_client, '/users', private_token: 'invalid') + + get request.url + + expect_status(401) + end + end +end diff --git a/qa/qa/specs/features/api/2_plan/.gitkeep b/qa/qa/specs/features/api/2_plan/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/qa/qa/specs/features/api/3_create/repository/files_spec.rb b/qa/qa/specs/features/api/3_create/repository/files_spec.rb new file mode 100644 index 00000000000..bc0b5ebfe10 --- /dev/null +++ b/qa/qa/specs/features/api/3_create/repository/files_spec.rb @@ -0,0 +1,61 @@ +require 'securerandom' + +module QA + describe 'API basics' do + before(:context) do + @api_client = Runtime::API::Client.new(:gitlab) + end + + let(:project_name) { "api-basics-#{SecureRandom.hex(8)}" } + let(:sanitized_project_path) { CGI.escape("#{Runtime::User.username}/#{project_name}") } + + it 'user creates a project with a file and deletes them afterwards' do + create_project_request = Runtime::API::Request.new(@api_client, '/projects') + post create_project_request.url, path: project_name, name: project_name + + expect_status(201) + expect(json_body).to match( + a_hash_including(name: project_name, path: project_name) + ) + + create_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md") + post create_file_request.url, branch: 'master', content: 'Hello world', commit_message: 'Add README.md' + + expect_status(201) + expect(json_body).to match( + a_hash_including(branch: 'master', file_path: 'README.md') + ) + + get_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", ref: 'master') + get get_file_request.url + + expect_status(200) + expect(json_body).to match( + a_hash_including( + ref: 'master', + file_path: 'README.md', file_name: 'README.md', + encoding: 'base64', content: 'SGVsbG8gd29ybGQ=' + ) + ) + + delete_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", branch: 'master', commit_message: 'Remove README.md') + delete delete_file_request.url + + expect_status(204) + + get_tree_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/tree") + get get_tree_request.url + + expect_status(200) + expect(json_body).to eq([]) + + delete_project_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}") + delete delete_project_request.url + + expect_status(202) + expect(json_body).to match( + a_hash_including(message: '202 Accepted') + ) + end + end +end diff --git a/qa/qa/specs/features/api/4_verify/.gitkeep b/qa/qa/specs/features/api/4_verify/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/qa/qa/specs/features/api/5_package/.gitkeep b/qa/qa/specs/features/api/5_package/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/qa/qa/specs/features/api/6_release/.gitkeep b/qa/qa/specs/features/api/6_release/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/qa/qa/specs/features/api/7_configure/.gitkeep b/qa/qa/specs/features/api/7_configure/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/qa/qa/specs/features/api/basics_spec.rb b/qa/qa/specs/features/api/basics_spec.rb deleted file mode 100644 index bc0b5ebfe10..00000000000 --- a/qa/qa/specs/features/api/basics_spec.rb +++ /dev/null @@ -1,61 +0,0 @@ -require 'securerandom' - -module QA - describe 'API basics' do - before(:context) do - @api_client = Runtime::API::Client.new(:gitlab) - end - - let(:project_name) { "api-basics-#{SecureRandom.hex(8)}" } - let(:sanitized_project_path) { CGI.escape("#{Runtime::User.username}/#{project_name}") } - - it 'user creates a project with a file and deletes them afterwards' do - create_project_request = Runtime::API::Request.new(@api_client, '/projects') - post create_project_request.url, path: project_name, name: project_name - - expect_status(201) - expect(json_body).to match( - a_hash_including(name: project_name, path: project_name) - ) - - create_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md") - post create_file_request.url, branch: 'master', content: 'Hello world', commit_message: 'Add README.md' - - expect_status(201) - expect(json_body).to match( - a_hash_including(branch: 'master', file_path: 'README.md') - ) - - get_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", ref: 'master') - get get_file_request.url - - expect_status(200) - expect(json_body).to match( - a_hash_including( - ref: 'master', - file_path: 'README.md', file_name: 'README.md', - encoding: 'base64', content: 'SGVsbG8gd29ybGQ=' - ) - ) - - delete_file_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/files/README.md", branch: 'master', commit_message: 'Remove README.md') - delete delete_file_request.url - - expect_status(204) - - get_tree_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}/repository/tree") - get get_tree_request.url - - expect_status(200) - expect(json_body).to eq([]) - - delete_project_request = Runtime::API::Request.new(@api_client, "/projects/#{sanitized_project_path}") - delete delete_project_request.url - - expect_status(202) - expect(json_body).to match( - a_hash_including(message: '202 Accepted') - ) - end - end -end diff --git a/qa/qa/specs/features/api/users_spec.rb b/qa/qa/specs/features/api/users_spec.rb deleted file mode 100644 index 3d25cca1e59..00000000000 --- a/qa/qa/specs/features/api/users_spec.rb +++ /dev/null @@ -1,41 +0,0 @@ -module QA - describe 'API users' do - before(:context) do - @api_client = Runtime::API::Client.new(:gitlab) - end - - context 'when authenticated' do - let(:request) { Runtime::API::Request.new(@api_client, '/users') } - - it 'get list of users' do - get request.url - - expect_status(200) - end - - it 'submit request with a valid user name' do - get request.url, { params: { username: Runtime::User.username } } - - expect_status(200) - expect(json_body).to contain_exactly( - a_hash_including(username: Runtime::User.username) - ) - end - - it 'submit request with an invalid user name' do - get request.url, { params: { username: SecureRandom.hex(10) } } - - expect_status(200) - expect(json_body).to eq([]) - end - end - - it 'submit request with an invalid token' do - request = Runtime::API::Request.new(@api_client, '/users', private_token: 'invalid') - - get request.url - - expect_status(401) - end - end -end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb new file mode 100644 index 00000000000..1c7da930567 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb @@ -0,0 +1,17 @@ +module QA + context :manage, :smoke do + describe 'basic user login' do + it 'user logs in using basic credentials' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + # TODO, since `Signed in successfully` message was removed + # this is the only way to tell if user is signed in correctly. + # + Page::Menu::Main.perform do |menu| + expect(menu).to have_personal_area + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb new file mode 100644 index 00000000000..de6111eea64 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb @@ -0,0 +1,19 @@ +module QA + describe 'LDAP user login', :orchestrated, :ldap do + before do + Runtime::Env.user_type = 'ldap' + end + + it 'user logs in using LDAP credentials' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + # TODO, since `Signed in successfully` message was removed + # this is the only way to tell if user is signed in correctly. + # + Page::Menu::Main.perform do |menu| + expect(menu).to have_personal_area + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb new file mode 100644 index 00000000000..27f7d4c245f --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb @@ -0,0 +1,17 @@ +module QA + describe 'logging in to Mattermost', :orchestrated, :mattermost do + it 'can use gitlab oauth' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) do + Page::Main::Login.act { sign_in_using_credentials } + + Runtime::Browser.visit(:mattermost, Page::Mattermost::Login) do + Page::Mattermost::Login.act { sign_in_using_oauth } + + Page::Mattermost::Main.perform do |page| + expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/) + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb new file mode 100644 index 00000000000..5e19e490778 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb @@ -0,0 +1,22 @@ +module QA + describe 'create a new project', :smoke do + it 'user creates a new project' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + created_project = Factory::Resource::Project.fabricate! do |project| + project.name = 'awesome-project' + project.description = 'create awesome project test' + end + + expect(created_project.name).to match /^awesome-project-\h{16}$/ + + expect(page).to have_content( + /Project \S?awesome-project\S+ was successfully created/ + ) + + expect(page).to have_content('create awesome project test') + expect(page).to have_content('The repository for this project is empty') + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb new file mode 100644 index 00000000000..57695d2c726 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb @@ -0,0 +1,106 @@ +module QA + describe 'user imports a GitHub repo', :orchestrated, :github do + let(:imported_project) do + Factory::Resource::ProjectImportedFromGithub.fabricate! do |project| + project.name = 'imported-project' + project.personal_access_token = Runtime::Env.github_access_token + project.github_repository_path = 'gitlab-qa/test-project' + end + end + + after do + # We need to delete the imported project because it's impossible to import + # the same GitHub project twice for a given user. + api_client = Runtime::API::Client.new(:gitlab) + delete_project_request = Runtime::API::Request.new(api_client, "/projects/#{CGI.escape("#{Runtime::Namespace.path}/#{imported_project.name}")}") + delete delete_project_request.url + + expect_status(202) + end + + it 'user imports a GitHub repo' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + imported_project # import the project + + Page::Menu::Main.act { go_to_projects } + Page::Dashboard::Projects.perform do |dashboard| + dashboard.go_to_project(imported_project.name) + end + + Page::Project::Show.act { wait_for_import } + + verify_repository_import + verify_issues_import + verify_merge_requests_import + verify_labels_import + verify_milestones_import + verify_wiki_import + end + + def verify_repository_import + expect(page).to have_content('This test project is used for automated GitHub import by GitLab QA.') + expect(page).to have_content(imported_project.name) + end + + def verify_issues_import + Page::Menu::Side.act { click_issues } + expect(page).to have_content('This is a sample issue') + + click_link 'This is a sample issue' + + expect(page).to have_content('We should populate this project with issues, pull requests and wiki pages.') + + # Comments + expect(page).to have_content('This is a comment from @rymai.') + + Page::Issuable::Sidebar.perform do |issuable| + expect(issuable).to have_label('enhancement') + expect(issuable).to have_label('help wanted') + expect(issuable).to have_label('good first issue') + end + end + + def verify_merge_requests_import + Page::Menu::Side.act { click_merge_requests } + expect(page).to have_content('Improve README.md') + + click_link 'Improve README.md' + + expect(page).to have_content('This improves the README file a bit.') + + # Review comment are not supported yet + expect(page).not_to have_content('Really nice change.') + + # Comments + expect(page).to have_content('Nice work! This is a comment from @rymai.') + + # Diff comments + expect(page).to have_content('[Review comment] I like that!') + expect(page).to have_content('[Review comment] Nice blank line.') + expect(page).to have_content('[Single diff comment] Much better without this line!') + + Page::Issuable::Sidebar.perform do |issuable| + expect(issuable).to have_label('bug') + expect(issuable).to have_label('enhancement') + end + end + + def verify_labels_import + # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19228 + # to build upon it. + end + + def verify_milestones_import + # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18727 + # to build upon it. + end + + def verify_wiki_import + Page::Menu::Side.act { click_wiki } + + expect(page).to have_content('Welcome to the test-project wiki!') + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb new file mode 100644 index 00000000000..c7ce8dfdcc6 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb @@ -0,0 +1,20 @@ +module QA + describe 'activity page' do + it 'push creates an event in the activity page' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + Factory::Repository::ProjectPush.fabricate! do |push| + push.file_name = 'README.md' + push.file_content = '# This is a test project' + push.commit_message = 'Add README.md' + end + + Page::Menu::Side.act { go_to_activity } + + Page::Project::Activity.act { go_to_push_events } + + expect(page).to have_content('pushed new branch master') + end + end +end diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb new file mode 100644 index 00000000000..793e7db87cb --- /dev/null +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb @@ -0,0 +1,18 @@ +module QA + describe 'creates issue', :smoke do + let(:issue_title) { 'issue title' } + + it 'user creates issue' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + Factory::Resource::Issue.fabricate! do |issue| + issue.title = issue_title + end + + Page::Menu::Side.act { click_issues } + + expect(page).to have_content(issue_title) + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb new file mode 100644 index 00000000000..71e79956b85 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb @@ -0,0 +1,53 @@ +module QA + describe 'creates a merge request with milestone' do + it 'user creates a new merge request' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + current_project = Factory::Resource::Project.fabricate! do |project| + project.name = 'project-with-merge-request-and-milestone' + end + + current_milestone = Factory::Resource::ProjectMilestone.fabricate! do |milestone| + milestone.title = 'unique-milestone' + milestone.project = current_project + end + + Factory::Resource::MergeRequest.fabricate! do |merge_request| + merge_request.title = 'This is a merge request with a milestone' + merge_request.description = 'Great feature with milestone' + merge_request.project = current_project + merge_request.milestone = current_milestone + end + + expect(page).to have_content('This is a merge request with a milestone') + expect(page).to have_content('Great feature with milestone') + expect(page).to have_content(/Opened [\w\s]+ ago/) + + Page::Issuable::Sidebar.perform do |sidebar| + expect(sidebar).to have_milestone(current_milestone.title) + end + end + end + + describe 'creates a merge request', :smoke do + it 'user creates a new merge request' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + current_project = Factory::Resource::Project.fabricate! do |project| + project.name = 'project-with-merge-request' + end + + Factory::Resource::MergeRequest.fabricate! do |merge_request| + merge_request.title = 'This is a merge request' + merge_request.description = 'Great feature' + merge_request.project = current_project + end + + expect(page).to have_content('This is a merge request') + expect(page).to have_content('Great feature') + expect(page).to have_content(/Opened [\w\s]+ ago/) + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb new file mode 100644 index 00000000000..280978bb950 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb @@ -0,0 +1,21 @@ +module QA + describe 'Project fork' do + it 'can submit merge requests to upstream master' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + merge_request = Factory::Resource::MergeRequestFromFork.fabricate! do |merge_request| + merge_request.fork_branch = 'feature-branch' + end + + Page::Menu::Main.perform { |main| main.sign_out } + Page::Main::Login.perform { |login| login.sign_in_using_credentials } + + merge_request.visit! + + Page::MergeRequest::Show.perform { |show| show.merge! } + + expect(page).to have_content('The changes were merged') + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb new file mode 100644 index 00000000000..c36d28e4237 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb @@ -0,0 +1,39 @@ +module QA + describe 'merge request rebase' do + it 'rebases source branch of merge request' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + project = Factory::Resource::Project.fabricate! do |project| + project.name = "only-fast-forward" + end + + Page::Menu::Side.act { go_to_settings } + Page::Project::Settings::MergeRequest.act { enable_ff_only } + + merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| + merge_request.project = project + merge_request.title = 'Needs rebasing' + end + + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.file_name = "other.txt" + push.file_content = "New file added!" + end + + merge_request.visit! + + Page::MergeRequest::Show.perform do |merge_request| + expect(merge_request).to have_content('Needs rebasing') + expect(merge_request).not_to be_fast_forward_possible + expect(merge_request).not_to have_merge_button + + merge_request.rebase! + + expect(merge_request).to have_merge_button + expect(merge_request.fast_forward_possible?).to be_truthy + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb new file mode 100644 index 00000000000..3ecc36a5ae1 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb @@ -0,0 +1,50 @@ +module QA + describe 'merge request squash commits' do + it 'when squash commits is marked before merge' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + project = Factory::Resource::Project.fabricate! do |project| + project.name = "squash-before-merge" + end + + merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| + merge_request.project = project + merge_request.title = 'Squashing commits' + end + + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.commit_message = 'to be squashed' + push.branch_name = merge_request.source_branch + push.new_branch = false + push.file_name = 'other.txt' + push.file_content = "Test with unicode characters ❤✓€❄" + end + + merge_request.visit! + + expect(page).to have_text('to be squashed') + + Page::MergeRequest::Show.perform do |merge_request_page| + merge_request_page.mark_to_squash + merge_request_page.merge! + + merge_request.project.visit! + + Git::Repository.perform do |repository| + repository.uri = Page::Project::Show.act do + choose_repository_clone_http + repository_location.uri + end + + repository.use_default_credentials + + repository.act { clone } + + expect(repository.commits.size).to eq 3 + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb new file mode 100644 index 00000000000..8b0613c5f78 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb @@ -0,0 +1,58 @@ +module QA + describe 'clone code from the repository' do + context 'with regular account over http' do + let(:location) do + Page::Project::Show.act do + choose_repository_clone_http + repository_location + end + end + + before do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + Factory::Resource::Project.fabricate! do |scenario| + scenario.name = 'project-with-code' + scenario.description = 'project for git clone tests' + end + + Git::Repository.perform do |repository| + repository.uri = location.uri + repository.use_default_credentials + + repository.act do + clone + configure_identity('GitLab QA', 'root@gitlab.com') + commit_file('test.rb', 'class Test; end', 'Add Test class') + commit_file('README.md', '# Test', 'Add Readme') + push_changes + end + end + end + + it 'user performs a deep clone' do + Git::Repository.perform do |repository| + repository.uri = location.uri + repository.use_default_credentials + + repository.act { clone } + + expect(repository.commits.size).to eq 2 + end + end + + it 'user performs a shallow clone' do + Git::Repository.perform do |repository| + repository.uri = location.uri + repository.use_default_credentials + + repository.act { shallow_clone } + + expect(repository.commits.size).to eq 1 + expect(repository.commits.first).to include 'Add Readme' + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb new file mode 100644 index 00000000000..5659784cd5c --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb @@ -0,0 +1,54 @@ +module QA + describe 'File Functionality', :core do + it 'lets a user create, edit and delete a file via WebUI' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + # Create + file_name = 'QA Test - File name' + file_content = 'QA Test - File content' + commit_message_for_create = 'QA Test - Create new file' + + Factory::Resource::File.fabricate! do |file| + file.name = file_name + file.content = file_content + file.commit_message = commit_message_for_create + end + + expect(page).to have_content('The file has been successfully created.') + expect(page).to have_content(file_name) + expect(page).to have_content(file_content) + expect(page).to have_content(commit_message_for_create) + + # Edit + updated_file_content = 'QA Test - Updated file content' + commit_message_for_update = 'QA Test - Update file' + + Page::File::Show.act { click_edit } + + Page::File::Form.act do + remove_content + add_content(updated_file_content) + add_commit_message(commit_message_for_update) + commit_changes + end + + expect(page).to have_content('Your changes have been successfully committed.') + expect(page).to have_content(updated_file_content) + expect(page).to have_content(commit_message_for_update) + + # Delete + commit_message_for_delete = 'QA Test - Delete file' + + Page::File::Show.act do + click_delete + add_commit_message(commit_message_for_delete) + click_delete_file + end + + expect(page).to have_content('The file has been successfully deleted.') + expect(page).to have_content(commit_message_for_delete) + expect(page).to have_no_content(file_name) + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb new file mode 100644 index 00000000000..1e89942e932 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb @@ -0,0 +1,21 @@ +module QA + describe 'push code to repository' do + context 'with regular account over http' do + it 'user pushes code to the repository' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + Factory::Repository::ProjectPush.fabricate! do |push| + push.file_name = 'README.md' + push.file_content = '# This is a test project' + push.commit_message = 'Add README.md' + end + + Page::Project::Show.act { wait_for_push } + + expect(page).to have_content('README.md') + expect(page).to have_content('This is a test project') + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb new file mode 100644 index 00000000000..aa23145478d --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb @@ -0,0 +1,66 @@ +module QA + describe 'branch protection support' do + let(:branch_name) { 'protected-branch' } + let(:commit_message) { 'Protected push commit message' } + let(:project) do + Factory::Resource::Project.fabricate! do |resource| + resource.name = 'protected-branch-project' + end + end + + before do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + end + + after do + # We need to clear localStorage because we're using it for the dropdown, + # and capybara doesn't do this for us. + # https://github.com/teamcapybara/capybara/issues/1702 + Capybara.execute_script 'localStorage.clear()' + end + + context 'when developers and maintainers are allowed to push to a protected branch' do + it 'user with push rights successfully pushes to the protected branch' do + create_protected_branch(allow_to_push: true) + + push = push_new_file(branch_name) + + expect(push.output).to match(/remote: To create a merge request for protected-branch, visit/) + end + end + + context 'when developers and maintainers are not allowed to push to a protected branch' do + it 'user without push rights fails to push to the protected branch' do + create_protected_branch(allow_to_push: false) + + push = push_new_file(branch_name) + + expect(push.output) + .to match(/remote\: GitLab\: You are not allowed to push code to protected branches on this project/) + expect(push.output) + .to match(/\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/) + end + end + + def create_protected_branch(allow_to_push:) + Factory::Resource::Branch.fabricate! do |resource| + resource.branch_name = branch_name + resource.project = project + resource.allow_to_push = allow_to_push + resource.protected = true + end + end + + def push_new_file(branch) + Factory::Repository::ProjectPush.fabricate! do |resource| + resource.project = project + resource.file_name = 'new_file.md' + resource.file_content = '# This is a new file' + resource.commit_message = 'Add new_file.md' + resource.branch_name = branch_name + resource.new_branch = false + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb new file mode 100644 index 00000000000..9af2dbd1264 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb @@ -0,0 +1,45 @@ +module QA + describe 'Wiki Functionality' do + def login + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + end + + def validate_content(content) + expect(page).to have_content('Wiki was successfully updated') + expect(page).to have_content(/#{content}/) + end + + before do + login + end + + it 'User creates, edits, clones, and pushes to the wiki' do + wiki = Factory::Resource::Wiki.fabricate! do |resource| + resource.title = 'Home' + resource.content = '# My First Wiki Content' + resource.message = 'Update home' + end + + validate_content('My First Wiki Content') + + Page::Project::Wiki::Edit.act { go_to_edit_page } + Page::Project::Wiki::New.perform do |page| + page.set_content("My Second Wiki Content") + page.save_changes + end + + validate_content('My Second Wiki Content') + + Factory::Repository::WikiPush.fabricate! do |push| + push.wiki = wiki + push.file_name = 'Home.md' + push.file_content = '# My Third Wiki Content' + push.commit_message = 'Update Home.md' + end + Page::Menu::Side.act { click_wiki } + + expect(page).to have_content('My Third Wiki Content') + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb new file mode 100644 index 00000000000..6c6b4e80626 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb @@ -0,0 +1,102 @@ +module QA + describe 'CI/CD Pipelines', :orchestrated, :docker do + let(:executor) { "qa-runner-#{Time.now.to_i}" } + + after do + Service::Runner.new(executor).remove! + end + + it 'user registers a new specific runner' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + Factory::Resource::Runner.fabricate! do |runner| + runner.name = executor + end + + Page::Project::Settings::CICD.perform do |settings| + sleep 5 # Runner should register within 5 seconds + settings.refresh + + settings.expand_runners_settings do |page| + expect(page).to have_content(executor) + expect(page).to have_online_runner + end + end + end + + it 'users creates a new pipeline' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + project = Factory::Resource::Project.fabricate! do |project| + project.name = 'project-with-pipelines' + project.description = 'Project with CI/CD Pipelines.' + end + + Factory::Resource::Runner.fabricate! do |runner| + runner.project = project + runner.name = executor + runner.tags = %w[qa test] + end + + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.file_name = '.gitlab-ci.yml' + push.commit_message = 'Add .gitlab-ci.yml' + push.file_content = <<~EOF + test-success: + tags: + - qa + - test + script: echo 'OK' + + test-failure: + tags: + - qa + - test + script: + - echo 'FAILURE' + - exit 1 + + test-tags: + tags: + - qa + - docker + script: echo 'NOOP' + + test-artifacts: + tags: + - qa + - test + script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt + artifacts: + paths: + - my-artifacts/ + EOF + end + + Page::Project::Show.act { wait_for_push } + + expect(page).to have_content('Add .gitlab-ci.yml') + + Page::Menu::Side.act { click_ci_cd_pipelines } + + expect(page).to have_content('All 1') + expect(page).to have_content('Add .gitlab-ci.yml') + + puts 'Waiting for the runner to process the pipeline' + sleep 15 # Runner should process all jobs within 15 seconds. + + Page::Project::Pipeline::Index.act { go_to_latest_pipeline } + + Page::Project::Pipeline::Show.perform do |pipeline| + expect(pipeline).to be_running + expect(pipeline).to have_build('test-success', status: :success) + expect(pipeline).to have_build('test-failure', status: :failed) + expect(pipeline).to have_build('test-tags', status: :pending) + expect(pipeline).to have_build('test-artifacts', status: :success) + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb new file mode 100644 index 00000000000..8d83a20f5bf --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module QA + context :verify, :docker do + describe 'Runner registration' do + let(:executor) { "qa-runner-#{Time.now.to_i}" } + + after do + Service::Runner.new(executor).remove! + end + + it 'user registers a new specific runner' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + Factory::Resource::Runner.fabricate! do |runner| + runner.name = executor + end + + Page::Project::Settings::CICD.perform do |settings| + sleep 5 # Runner should register within 5 seconds + settings.refresh + + settings.expand_runners_settings do |page| + expect(page).to have_content(executor) + expect(page).to have_online_runner + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb new file mode 100644 index 00000000000..04d9fe488e2 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb @@ -0,0 +1,24 @@ +module QA + describe 'secret variables support' do + it 'user adds a secret variable' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.key = 'VARIABLE_KEY' + resource.value = 'some secret variable' + end + + Page::Project::Settings::CICD.perform do |settings| + settings.expand_secret_variables do |page| + expect(page).to have_field(with: 'VARIABLE_KEY') + expect(page).not_to have_field(with: 'some secret variable') + + page.reveal_variables + + expect(page).to have_field(with: 'some secret variable') + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/5_package/.gitkeep b/qa/qa/specs/features/browser_ui/5_package/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb new file mode 100644 index 00000000000..24f9f4c77f8 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb @@ -0,0 +1,19 @@ +module QA + describe 'deploy keys support' do + it 'user adds a deploy key' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + key = Runtime::Key::RSA.new + deploy_key_title = 'deploy key title' + deploy_key_value = key.public_key + + deploy_key = Factory::Resource::DeployKey.fabricate! do |resource| + resource.title = deploy_key_title + resource.key = deploy_key_value + end + + expect(deploy_key.fingerprint).to eq(key.fingerprint) + end + end +end diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb new file mode 100644 index 00000000000..1d099508c24 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb @@ -0,0 +1,105 @@ +require 'digest/sha1' + +module QA + describe 'cloning code using a deploy key', :docker do + def login + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + end + + before(:all) do + login + + @runner_name = "qa-runner-#{Time.now.to_i}" + + @project = Factory::Resource::Project.fabricate! do |resource| + resource.name = 'deploy-key-clone-project' + end + + @repository_location = @project.repository_ssh_location + + Factory::Resource::Runner.fabricate! do |resource| + resource.project = @project + resource.name = @runner_name + resource.tags = %w[qa docker] + resource.image = 'gitlab/gitlab-runner:ubuntu' + end + + Page::Menu::Main.act { sign_out } + end + + after(:all) do + Service::Runner.new(@runner_name).remove! + end + + keys = [ + [Runtime::Key::RSA, 8192], + [Runtime::Key::ECDSA, 521], + [Runtime::Key::ED25519] + ] + + keys.each do |(key_class, bits)| + it "user sets up a deploy key with #{key_class}(#{bits}) to clone code using pipelines" do + key = key_class.new(*bits) + + login + + Factory::Resource::DeployKey.fabricate! do |resource| + resource.project = @project + resource.title = "deploy key #{key.name}(#{key.bits})" + resource.key = key.public_key + end + + deploy_key_name = "DEPLOY_KEY_#{key.name}_#{key.bits}" + + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.project = @project + resource.key = deploy_key_name + resource.value = key.private_key + end + + gitlab_ci = <<~YAML + cat-config: + script: + - mkdir -p ~/.ssh + - ssh-keyscan -p #{@repository_location.port} #{@repository_location.host} >> ~/.ssh/known_hosts + - eval $(ssh-agent -s) + - ssh-add -D + - echo "$#{deploy_key_name}" | ssh-add - + - git clone #{@repository_location.git_uri} + - cd #{@project.name} + - git checkout #{deploy_key_name} + - sha1sum .gitlab-ci.yml + tags: + - qa + - docker + YAML + + Factory::Repository::ProjectPush.fabricate! do |resource| + resource.project = @project + resource.file_name = '.gitlab-ci.yml' + resource.commit_message = 'Add .gitlab-ci.yml' + resource.file_content = gitlab_ci + resource.branch_name = deploy_key_name + resource.new_branch = true + end + + sha1sum = Digest::SHA1.hexdigest(gitlab_ci) + + Page::Project::Show.act { wait_for_push } + Page::Menu::Side.act { click_ci_cd_pipelines } + Page::Project::Pipeline::Index.act { go_to_latest_pipeline } + Page::Project::Pipeline::Show.act { go_to_first_job } + + Page::Project::Job::Show.perform do |job| + job.wait(reload: false) do + job.completed? && !job.trace_loading? + end + + expect(job.passed?).to be_truthy, "Job status did not become \"passed\"." + expect(job.output).to include(sha1sum) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb new file mode 100644 index 00000000000..248669b6046 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb @@ -0,0 +1,64 @@ +require 'pathname' + +module QA + describe 'Auto Devops', :orchestrated, :kubernetes do + after do + @cluster&.remove! + end + + it 'user creates a new project and runs auto devops' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + project = Factory::Resource::Project.fabricate! do |p| + p.name = 'project-with-autodevops' + p.description = 'Project with Auto Devops' + end + + # Disable code_quality check in Auto DevOps pipeline as it takes + # too long and times out the test + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.key = 'CODE_QUALITY_DISABLED' + resource.value = '1' + end + + # Create Auto Devops compatible repo + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.directory = Pathname + .new(__dir__) + .join('../../../fixtures/auto_devops_rack') + push.commit_message = 'Create Auto DevOps compatible rack application' + end + + Page::Project::Show.act { wait_for_push } + + # Create and connect K8s cluster + @cluster = Service::KubernetesCluster.new.create! + kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster| + cluster.project = project + cluster.cluster = @cluster + cluster.install_helm_tiller = true + cluster.install_ingress = true + cluster.install_prometheus = true + cluster.install_runner = true + end + + project.visit! + Page::Menu::Side.act { click_ci_cd_settings } + Page::Project::Settings::CICD.perform do |p| + p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io") + end + + project.visit! + Page::Menu::Side.act { click_ci_cd_pipelines } + Page::Project::Pipeline::Index.act { go_to_latest_pipeline } + + Page::Project::Pipeline::Show.perform do |pipeline| + expect(pipeline).to have_build('build', status: :success, wait: 600) + expect(pipeline).to have_build('test', status: :success, wait: 600) + expect(pipeline).to have_build('production', status: :success, wait: 1200) + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb new file mode 100644 index 00000000000..097e1713aef --- /dev/null +++ b/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb @@ -0,0 +1,17 @@ +module QA + describe 'create a new group', :orchestrated, :mattermost do + it 'creating a group with a mattermost team' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + Page::Menu::Main.act { go_to_groups } + + Page::Dashboard::Groups.perform do |page| + page.go_to_new_group + + expect(page).to have_content( + /Create a Mattermost team for this group/ + ) + end + end + end +end diff --git a/qa/qa/specs/features/login/ldap_spec.rb b/qa/qa/specs/features/login/ldap_spec.rb deleted file mode 100644 index de6111eea64..00000000000 --- a/qa/qa/specs/features/login/ldap_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -module QA - describe 'LDAP user login', :orchestrated, :ldap do - before do - Runtime::Env.user_type = 'ldap' - end - - it 'user logs in using LDAP credentials' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - # TODO, since `Signed in successfully` message was removed - # this is the only way to tell if user is signed in correctly. - # - Page::Menu::Main.perform do |menu| - expect(menu).to have_personal_area - end - end - end -end diff --git a/qa/qa/specs/features/mattermost/group_create_spec.rb b/qa/qa/specs/features/mattermost/group_create_spec.rb deleted file mode 100644 index 097e1713aef..00000000000 --- a/qa/qa/specs/features/mattermost/group_create_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -module QA - describe 'create a new group', :orchestrated, :mattermost do - it 'creating a group with a mattermost team' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - Page::Menu::Main.act { go_to_groups } - - Page::Dashboard::Groups.perform do |page| - page.go_to_new_group - - expect(page).to have_content( - /Create a Mattermost team for this group/ - ) - end - end - end -end diff --git a/qa/qa/specs/features/mattermost/login_spec.rb b/qa/qa/specs/features/mattermost/login_spec.rb deleted file mode 100644 index 27f7d4c245f..00000000000 --- a/qa/qa/specs/features/mattermost/login_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -module QA - describe 'logging in to Mattermost', :orchestrated, :mattermost do - it 'can use gitlab oauth' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) do - Page::Main::Login.act { sign_in_using_credentials } - - Runtime::Browser.visit(:mattermost, Page::Mattermost::Login) do - Page::Mattermost::Login.act { sign_in_using_oauth } - - Page::Mattermost::Main.perform do |page| - expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/) - end - end - end - end - end -end diff --git a/qa/qa/specs/features/merge_request/create_spec.rb b/qa/qa/specs/features/merge_request/create_spec.rb deleted file mode 100644 index 71e79956b85..00000000000 --- a/qa/qa/specs/features/merge_request/create_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -module QA - describe 'creates a merge request with milestone' do - it 'user creates a new merge request' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - current_project = Factory::Resource::Project.fabricate! do |project| - project.name = 'project-with-merge-request-and-milestone' - end - - current_milestone = Factory::Resource::ProjectMilestone.fabricate! do |milestone| - milestone.title = 'unique-milestone' - milestone.project = current_project - end - - Factory::Resource::MergeRequest.fabricate! do |merge_request| - merge_request.title = 'This is a merge request with a milestone' - merge_request.description = 'Great feature with milestone' - merge_request.project = current_project - merge_request.milestone = current_milestone - end - - expect(page).to have_content('This is a merge request with a milestone') - expect(page).to have_content('Great feature with milestone') - expect(page).to have_content(/Opened [\w\s]+ ago/) - - Page::Issuable::Sidebar.perform do |sidebar| - expect(sidebar).to have_milestone(current_milestone.title) - end - end - end - - describe 'creates a merge request', :smoke do - it 'user creates a new merge request' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - current_project = Factory::Resource::Project.fabricate! do |project| - project.name = 'project-with-merge-request' - end - - Factory::Resource::MergeRequest.fabricate! do |merge_request| - merge_request.title = 'This is a merge request' - merge_request.description = 'Great feature' - merge_request.project = current_project - end - - expect(page).to have_content('This is a merge request') - expect(page).to have_content('Great feature') - expect(page).to have_content(/Opened [\w\s]+ ago/) - end - end -end diff --git a/qa/qa/specs/features/merge_request/rebase_spec.rb b/qa/qa/specs/features/merge_request/rebase_spec.rb deleted file mode 100644 index c36d28e4237..00000000000 --- a/qa/qa/specs/features/merge_request/rebase_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -module QA - describe 'merge request rebase' do - it 'rebases source branch of merge request' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - project = Factory::Resource::Project.fabricate! do |project| - project.name = "only-fast-forward" - end - - Page::Menu::Side.act { go_to_settings } - Page::Project::Settings::MergeRequest.act { enable_ff_only } - - merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| - merge_request.project = project - merge_request.title = 'Needs rebasing' - end - - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.file_name = "other.txt" - push.file_content = "New file added!" - end - - merge_request.visit! - - Page::MergeRequest::Show.perform do |merge_request| - expect(merge_request).to have_content('Needs rebasing') - expect(merge_request).not_to be_fast_forward_possible - expect(merge_request).not_to have_merge_button - - merge_request.rebase! - - expect(merge_request).to have_merge_button - expect(merge_request.fast_forward_possible?).to be_truthy - end - end - end -end diff --git a/qa/qa/specs/features/merge_request/squash_spec.rb b/qa/qa/specs/features/merge_request/squash_spec.rb deleted file mode 100644 index 3ecc36a5ae1..00000000000 --- a/qa/qa/specs/features/merge_request/squash_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -module QA - describe 'merge request squash commits' do - it 'when squash commits is marked before merge' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - project = Factory::Resource::Project.fabricate! do |project| - project.name = "squash-before-merge" - end - - merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| - merge_request.project = project - merge_request.title = 'Squashing commits' - end - - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.commit_message = 'to be squashed' - push.branch_name = merge_request.source_branch - push.new_branch = false - push.file_name = 'other.txt' - push.file_content = "Test with unicode characters ❤✓€❄" - end - - merge_request.visit! - - expect(page).to have_text('to be squashed') - - Page::MergeRequest::Show.perform do |merge_request_page| - merge_request_page.mark_to_squash - merge_request_page.merge! - - merge_request.project.visit! - - Git::Repository.perform do |repository| - repository.uri = Page::Project::Show.act do - choose_repository_clone_http - repository_location.uri - end - - repository.use_default_credentials - - repository.act { clone } - - expect(repository.commits.size).to eq 3 - end - end - end - end -end diff --git a/qa/qa/specs/features/project/activity_spec.rb b/qa/qa/specs/features/project/activity_spec.rb deleted file mode 100644 index c7ce8dfdcc6..00000000000 --- a/qa/qa/specs/features/project/activity_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -module QA - describe 'activity page' do - it 'push creates an event in the activity page' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - Factory::Repository::ProjectPush.fabricate! do |push| - push.file_name = 'README.md' - push.file_content = '# This is a test project' - push.commit_message = 'Add README.md' - end - - Page::Menu::Side.act { go_to_activity } - - Page::Project::Activity.act { go_to_push_events } - - expect(page).to have_content('pushed new branch master') - end - end -end diff --git a/qa/qa/specs/features/project/add_deploy_key_spec.rb b/qa/qa/specs/features/project/add_deploy_key_spec.rb deleted file mode 100644 index 24f9f4c77f8..00000000000 --- a/qa/qa/specs/features/project/add_deploy_key_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -module QA - describe 'deploy keys support' do - it 'user adds a deploy key' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - key = Runtime::Key::RSA.new - deploy_key_title = 'deploy key title' - deploy_key_value = key.public_key - - deploy_key = Factory::Resource::DeployKey.fabricate! do |resource| - resource.title = deploy_key_title - resource.key = deploy_key_value - end - - expect(deploy_key.fingerprint).to eq(key.fingerprint) - end - end -end diff --git a/qa/qa/specs/features/project/add_secret_variable_spec.rb b/qa/qa/specs/features/project/add_secret_variable_spec.rb deleted file mode 100644 index 04d9fe488e2..00000000000 --- a/qa/qa/specs/features/project/add_secret_variable_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -module QA - describe 'secret variables support' do - it 'user adds a secret variable' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - Factory::Resource::SecretVariable.fabricate! do |resource| - resource.key = 'VARIABLE_KEY' - resource.value = 'some secret variable' - end - - Page::Project::Settings::CICD.perform do |settings| - settings.expand_secret_variables do |page| - expect(page).to have_field(with: 'VARIABLE_KEY') - expect(page).not_to have_field(with: 'some secret variable') - - page.reveal_variables - - expect(page).to have_field(with: 'some secret variable') - end - end - end - end -end diff --git a/qa/qa/specs/features/project/auto_devops_spec.rb b/qa/qa/specs/features/project/auto_devops_spec.rb deleted file mode 100644 index 248669b6046..00000000000 --- a/qa/qa/specs/features/project/auto_devops_spec.rb +++ /dev/null @@ -1,64 +0,0 @@ -require 'pathname' - -module QA - describe 'Auto Devops', :orchestrated, :kubernetes do - after do - @cluster&.remove! - end - - it 'user creates a new project and runs auto devops' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - project = Factory::Resource::Project.fabricate! do |p| - p.name = 'project-with-autodevops' - p.description = 'Project with Auto Devops' - end - - # Disable code_quality check in Auto DevOps pipeline as it takes - # too long and times out the test - Factory::Resource::SecretVariable.fabricate! do |resource| - resource.key = 'CODE_QUALITY_DISABLED' - resource.value = '1' - end - - # Create Auto Devops compatible repo - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.directory = Pathname - .new(__dir__) - .join('../../../fixtures/auto_devops_rack') - push.commit_message = 'Create Auto DevOps compatible rack application' - end - - Page::Project::Show.act { wait_for_push } - - # Create and connect K8s cluster - @cluster = Service::KubernetesCluster.new.create! - kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster| - cluster.project = project - cluster.cluster = @cluster - cluster.install_helm_tiller = true - cluster.install_ingress = true - cluster.install_prometheus = true - cluster.install_runner = true - end - - project.visit! - Page::Menu::Side.act { click_ci_cd_settings } - Page::Project::Settings::CICD.perform do |p| - p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io") - end - - project.visit! - Page::Menu::Side.act { click_ci_cd_pipelines } - Page::Project::Pipeline::Index.act { go_to_latest_pipeline } - - Page::Project::Pipeline::Show.perform do |pipeline| - expect(pipeline).to have_build('build', status: :success, wait: 600) - expect(pipeline).to have_build('test', status: :success, wait: 600) - expect(pipeline).to have_build('production', status: :success, wait: 1200) - end - end - end -end diff --git a/qa/qa/specs/features/project/create_issue_spec.rb b/qa/qa/specs/features/project/create_issue_spec.rb deleted file mode 100644 index 793e7db87cb..00000000000 --- a/qa/qa/specs/features/project/create_issue_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -module QA - describe 'creates issue', :smoke do - let(:issue_title) { 'issue title' } - - it 'user creates issue' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - Factory::Resource::Issue.fabricate! do |issue| - issue.title = issue_title - end - - Page::Menu::Side.act { click_issues } - - expect(page).to have_content(issue_title) - end - end -end diff --git a/qa/qa/specs/features/project/create_spec.rb b/qa/qa/specs/features/project/create_spec.rb deleted file mode 100644 index 5e19e490778..00000000000 --- a/qa/qa/specs/features/project/create_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -module QA - describe 'create a new project', :smoke do - it 'user creates a new project' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - created_project = Factory::Resource::Project.fabricate! do |project| - project.name = 'awesome-project' - project.description = 'create awesome project test' - end - - expect(created_project.name).to match /^awesome-project-\h{16}$/ - - expect(page).to have_content( - /Project \S?awesome-project\S+ was successfully created/ - ) - - expect(page).to have_content('create awesome project test') - expect(page).to have_content('The repository for this project is empty') - end - end -end diff --git a/qa/qa/specs/features/project/deploy_key_clone_spec.rb b/qa/qa/specs/features/project/deploy_key_clone_spec.rb deleted file mode 100644 index 1d099508c24..00000000000 --- a/qa/qa/specs/features/project/deploy_key_clone_spec.rb +++ /dev/null @@ -1,105 +0,0 @@ -require 'digest/sha1' - -module QA - describe 'cloning code using a deploy key', :docker do - def login - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - end - - before(:all) do - login - - @runner_name = "qa-runner-#{Time.now.to_i}" - - @project = Factory::Resource::Project.fabricate! do |resource| - resource.name = 'deploy-key-clone-project' - end - - @repository_location = @project.repository_ssh_location - - Factory::Resource::Runner.fabricate! do |resource| - resource.project = @project - resource.name = @runner_name - resource.tags = %w[qa docker] - resource.image = 'gitlab/gitlab-runner:ubuntu' - end - - Page::Menu::Main.act { sign_out } - end - - after(:all) do - Service::Runner.new(@runner_name).remove! - end - - keys = [ - [Runtime::Key::RSA, 8192], - [Runtime::Key::ECDSA, 521], - [Runtime::Key::ED25519] - ] - - keys.each do |(key_class, bits)| - it "user sets up a deploy key with #{key_class}(#{bits}) to clone code using pipelines" do - key = key_class.new(*bits) - - login - - Factory::Resource::DeployKey.fabricate! do |resource| - resource.project = @project - resource.title = "deploy key #{key.name}(#{key.bits})" - resource.key = key.public_key - end - - deploy_key_name = "DEPLOY_KEY_#{key.name}_#{key.bits}" - - Factory::Resource::SecretVariable.fabricate! do |resource| - resource.project = @project - resource.key = deploy_key_name - resource.value = key.private_key - end - - gitlab_ci = <<~YAML - cat-config: - script: - - mkdir -p ~/.ssh - - ssh-keyscan -p #{@repository_location.port} #{@repository_location.host} >> ~/.ssh/known_hosts - - eval $(ssh-agent -s) - - ssh-add -D - - echo "$#{deploy_key_name}" | ssh-add - - - git clone #{@repository_location.git_uri} - - cd #{@project.name} - - git checkout #{deploy_key_name} - - sha1sum .gitlab-ci.yml - tags: - - qa - - docker - YAML - - Factory::Repository::ProjectPush.fabricate! do |resource| - resource.project = @project - resource.file_name = '.gitlab-ci.yml' - resource.commit_message = 'Add .gitlab-ci.yml' - resource.file_content = gitlab_ci - resource.branch_name = deploy_key_name - resource.new_branch = true - end - - sha1sum = Digest::SHA1.hexdigest(gitlab_ci) - - Page::Project::Show.act { wait_for_push } - Page::Menu::Side.act { click_ci_cd_pipelines } - Page::Project::Pipeline::Index.act { go_to_latest_pipeline } - Page::Project::Pipeline::Show.act { go_to_first_job } - - Page::Project::Job::Show.perform do |job| - job.wait(reload: false) do - job.completed? && !job.trace_loading? - end - - expect(job.passed?).to be_truthy, "Job status did not become \"passed\"." - expect(job.output).to include(sha1sum) - end - end - end - end -end diff --git a/qa/qa/specs/features/project/file_spec.rb b/qa/qa/specs/features/project/file_spec.rb deleted file mode 100644 index 5659784cd5c..00000000000 --- a/qa/qa/specs/features/project/file_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -module QA - describe 'File Functionality', :core do - it 'lets a user create, edit and delete a file via WebUI' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - # Create - file_name = 'QA Test - File name' - file_content = 'QA Test - File content' - commit_message_for_create = 'QA Test - Create new file' - - Factory::Resource::File.fabricate! do |file| - file.name = file_name - file.content = file_content - file.commit_message = commit_message_for_create - end - - expect(page).to have_content('The file has been successfully created.') - expect(page).to have_content(file_name) - expect(page).to have_content(file_content) - expect(page).to have_content(commit_message_for_create) - - # Edit - updated_file_content = 'QA Test - Updated file content' - commit_message_for_update = 'QA Test - Update file' - - Page::File::Show.act { click_edit } - - Page::File::Form.act do - remove_content - add_content(updated_file_content) - add_commit_message(commit_message_for_update) - commit_changes - end - - expect(page).to have_content('Your changes have been successfully committed.') - expect(page).to have_content(updated_file_content) - expect(page).to have_content(commit_message_for_update) - - # Delete - commit_message_for_delete = 'QA Test - Delete file' - - Page::File::Show.act do - click_delete - add_commit_message(commit_message_for_delete) - click_delete_file - end - - expect(page).to have_content('The file has been successfully deleted.') - expect(page).to have_content(commit_message_for_delete) - expect(page).to have_no_content(file_name) - end - end -end diff --git a/qa/qa/specs/features/project/fork_project_spec.rb b/qa/qa/specs/features/project/fork_project_spec.rb deleted file mode 100644 index 280978bb950..00000000000 --- a/qa/qa/specs/features/project/fork_project_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -module QA - describe 'Project fork' do - it 'can submit merge requests to upstream master' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - merge_request = Factory::Resource::MergeRequestFromFork.fabricate! do |merge_request| - merge_request.fork_branch = 'feature-branch' - end - - Page::Menu::Main.perform { |main| main.sign_out } - Page::Main::Login.perform { |login| login.sign_in_using_credentials } - - merge_request.visit! - - Page::MergeRequest::Show.perform { |show| show.merge! } - - expect(page).to have_content('The changes were merged') - end - end -end diff --git a/qa/qa/specs/features/project/import_from_github_spec.rb b/qa/qa/specs/features/project/import_from_github_spec.rb deleted file mode 100644 index 57695d2c726..00000000000 --- a/qa/qa/specs/features/project/import_from_github_spec.rb +++ /dev/null @@ -1,106 +0,0 @@ -module QA - describe 'user imports a GitHub repo', :orchestrated, :github do - let(:imported_project) do - Factory::Resource::ProjectImportedFromGithub.fabricate! do |project| - project.name = 'imported-project' - project.personal_access_token = Runtime::Env.github_access_token - project.github_repository_path = 'gitlab-qa/test-project' - end - end - - after do - # We need to delete the imported project because it's impossible to import - # the same GitHub project twice for a given user. - api_client = Runtime::API::Client.new(:gitlab) - delete_project_request = Runtime::API::Request.new(api_client, "/projects/#{CGI.escape("#{Runtime::Namespace.path}/#{imported_project.name}")}") - delete delete_project_request.url - - expect_status(202) - end - - it 'user imports a GitHub repo' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - imported_project # import the project - - Page::Menu::Main.act { go_to_projects } - Page::Dashboard::Projects.perform do |dashboard| - dashboard.go_to_project(imported_project.name) - end - - Page::Project::Show.act { wait_for_import } - - verify_repository_import - verify_issues_import - verify_merge_requests_import - verify_labels_import - verify_milestones_import - verify_wiki_import - end - - def verify_repository_import - expect(page).to have_content('This test project is used for automated GitHub import by GitLab QA.') - expect(page).to have_content(imported_project.name) - end - - def verify_issues_import - Page::Menu::Side.act { click_issues } - expect(page).to have_content('This is a sample issue') - - click_link 'This is a sample issue' - - expect(page).to have_content('We should populate this project with issues, pull requests and wiki pages.') - - # Comments - expect(page).to have_content('This is a comment from @rymai.') - - Page::Issuable::Sidebar.perform do |issuable| - expect(issuable).to have_label('enhancement') - expect(issuable).to have_label('help wanted') - expect(issuable).to have_label('good first issue') - end - end - - def verify_merge_requests_import - Page::Menu::Side.act { click_merge_requests } - expect(page).to have_content('Improve README.md') - - click_link 'Improve README.md' - - expect(page).to have_content('This improves the README file a bit.') - - # Review comment are not supported yet - expect(page).not_to have_content('Really nice change.') - - # Comments - expect(page).to have_content('Nice work! This is a comment from @rymai.') - - # Diff comments - expect(page).to have_content('[Review comment] I like that!') - expect(page).to have_content('[Review comment] Nice blank line.') - expect(page).to have_content('[Single diff comment] Much better without this line!') - - Page::Issuable::Sidebar.perform do |issuable| - expect(issuable).to have_label('bug') - expect(issuable).to have_label('enhancement') - end - end - - def verify_labels_import - # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19228 - # to build upon it. - end - - def verify_milestones_import - # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18727 - # to build upon it. - end - - def verify_wiki_import - Page::Menu::Side.act { click_wiki } - - expect(page).to have_content('Welcome to the test-project wiki!') - end - end -end diff --git a/qa/qa/specs/features/project/pipelines_spec.rb b/qa/qa/specs/features/project/pipelines_spec.rb deleted file mode 100644 index 6c6b4e80626..00000000000 --- a/qa/qa/specs/features/project/pipelines_spec.rb +++ /dev/null @@ -1,102 +0,0 @@ -module QA - describe 'CI/CD Pipelines', :orchestrated, :docker do - let(:executor) { "qa-runner-#{Time.now.to_i}" } - - after do - Service::Runner.new(executor).remove! - end - - it 'user registers a new specific runner' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - Factory::Resource::Runner.fabricate! do |runner| - runner.name = executor - end - - Page::Project::Settings::CICD.perform do |settings| - sleep 5 # Runner should register within 5 seconds - settings.refresh - - settings.expand_runners_settings do |page| - expect(page).to have_content(executor) - expect(page).to have_online_runner - end - end - end - - it 'users creates a new pipeline' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - project = Factory::Resource::Project.fabricate! do |project| - project.name = 'project-with-pipelines' - project.description = 'Project with CI/CD Pipelines.' - end - - Factory::Resource::Runner.fabricate! do |runner| - runner.project = project - runner.name = executor - runner.tags = %w[qa test] - end - - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.file_name = '.gitlab-ci.yml' - push.commit_message = 'Add .gitlab-ci.yml' - push.file_content = <<~EOF - test-success: - tags: - - qa - - test - script: echo 'OK' - - test-failure: - tags: - - qa - - test - script: - - echo 'FAILURE' - - exit 1 - - test-tags: - tags: - - qa - - docker - script: echo 'NOOP' - - test-artifacts: - tags: - - qa - - test - script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt - artifacts: - paths: - - my-artifacts/ - EOF - end - - Page::Project::Show.act { wait_for_push } - - expect(page).to have_content('Add .gitlab-ci.yml') - - Page::Menu::Side.act { click_ci_cd_pipelines } - - expect(page).to have_content('All 1') - expect(page).to have_content('Add .gitlab-ci.yml') - - puts 'Waiting for the runner to process the pipeline' - sleep 15 # Runner should process all jobs within 15 seconds. - - Page::Project::Pipeline::Index.act { go_to_latest_pipeline } - - Page::Project::Pipeline::Show.perform do |pipeline| - expect(pipeline).to be_running - expect(pipeline).to have_build('test-success', status: :success) - expect(pipeline).to have_build('test-failure', status: :failed) - expect(pipeline).to have_build('test-tags', status: :pending) - expect(pipeline).to have_build('test-artifacts', status: :success) - end - end - end -end diff --git a/qa/qa/specs/features/project/wikis_spec.rb b/qa/qa/specs/features/project/wikis_spec.rb deleted file mode 100644 index 9af2dbd1264..00000000000 --- a/qa/qa/specs/features/project/wikis_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -module QA - describe 'Wiki Functionality' do - def login - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - end - - def validate_content(content) - expect(page).to have_content('Wiki was successfully updated') - expect(page).to have_content(/#{content}/) - end - - before do - login - end - - it 'User creates, edits, clones, and pushes to the wiki' do - wiki = Factory::Resource::Wiki.fabricate! do |resource| - resource.title = 'Home' - resource.content = '# My First Wiki Content' - resource.message = 'Update home' - end - - validate_content('My First Wiki Content') - - Page::Project::Wiki::Edit.act { go_to_edit_page } - Page::Project::Wiki::New.perform do |page| - page.set_content("My Second Wiki Content") - page.save_changes - end - - validate_content('My Second Wiki Content') - - Factory::Repository::WikiPush.fabricate! do |push| - push.wiki = wiki - push.file_name = 'Home.md' - push.file_content = '# My Third Wiki Content' - push.commit_message = 'Update Home.md' - end - Page::Menu::Side.act { click_wiki } - - expect(page).to have_content('My Third Wiki Content') - end - end -end diff --git a/qa/qa/specs/features/repository/clone_spec.rb b/qa/qa/specs/features/repository/clone_spec.rb deleted file mode 100644 index 8b0613c5f78..00000000000 --- a/qa/qa/specs/features/repository/clone_spec.rb +++ /dev/null @@ -1,58 +0,0 @@ -module QA - describe 'clone code from the repository' do - context 'with regular account over http' do - let(:location) do - Page::Project::Show.act do - choose_repository_clone_http - repository_location - end - end - - before do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - Factory::Resource::Project.fabricate! do |scenario| - scenario.name = 'project-with-code' - scenario.description = 'project for git clone tests' - end - - Git::Repository.perform do |repository| - repository.uri = location.uri - repository.use_default_credentials - - repository.act do - clone - configure_identity('GitLab QA', 'root@gitlab.com') - commit_file('test.rb', 'class Test; end', 'Add Test class') - commit_file('README.md', '# Test', 'Add Readme') - push_changes - end - end - end - - it 'user performs a deep clone' do - Git::Repository.perform do |repository| - repository.uri = location.uri - repository.use_default_credentials - - repository.act { clone } - - expect(repository.commits.size).to eq 2 - end - end - - it 'user performs a shallow clone' do - Git::Repository.perform do |repository| - repository.uri = location.uri - repository.use_default_credentials - - repository.act { shallow_clone } - - expect(repository.commits.size).to eq 1 - expect(repository.commits.first).to include 'Add Readme' - end - end - end - end -end diff --git a/qa/qa/specs/features/repository/protected_branches_spec.rb b/qa/qa/specs/features/repository/protected_branches_spec.rb deleted file mode 100644 index aa23145478d..00000000000 --- a/qa/qa/specs/features/repository/protected_branches_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -module QA - describe 'branch protection support' do - let(:branch_name) { 'protected-branch' } - let(:commit_message) { 'Protected push commit message' } - let(:project) do - Factory::Resource::Project.fabricate! do |resource| - resource.name = 'protected-branch-project' - end - end - - before do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - end - - after do - # We need to clear localStorage because we're using it for the dropdown, - # and capybara doesn't do this for us. - # https://github.com/teamcapybara/capybara/issues/1702 - Capybara.execute_script 'localStorage.clear()' - end - - context 'when developers and maintainers are allowed to push to a protected branch' do - it 'user with push rights successfully pushes to the protected branch' do - create_protected_branch(allow_to_push: true) - - push = push_new_file(branch_name) - - expect(push.output).to match(/remote: To create a merge request for protected-branch, visit/) - end - end - - context 'when developers and maintainers are not allowed to push to a protected branch' do - it 'user without push rights fails to push to the protected branch' do - create_protected_branch(allow_to_push: false) - - push = push_new_file(branch_name) - - expect(push.output) - .to match(/remote\: GitLab\: You are not allowed to push code to protected branches on this project/) - expect(push.output) - .to match(/\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/) - end - end - - def create_protected_branch(allow_to_push:) - Factory::Resource::Branch.fabricate! do |resource| - resource.branch_name = branch_name - resource.project = project - resource.allow_to_push = allow_to_push - resource.protected = true - end - end - - def push_new_file(branch) - Factory::Repository::ProjectPush.fabricate! do |resource| - resource.project = project - resource.file_name = 'new_file.md' - resource.file_content = '# This is a new file' - resource.commit_message = 'Add new_file.md' - resource.branch_name = branch_name - resource.new_branch = false - end - end - end -end diff --git a/qa/qa/specs/features/repository/push_spec.rb b/qa/qa/specs/features/repository/push_spec.rb deleted file mode 100644 index 1e89942e932..00000000000 --- a/qa/qa/specs/features/repository/push_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -module QA - describe 'push code to repository' do - context 'with regular account over http' do - it 'user pushes code to the repository' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - Factory::Repository::ProjectPush.fabricate! do |push| - push.file_name = 'README.md' - push.file_content = '# This is a test project' - push.commit_message = 'Add README.md' - end - - Page::Project::Show.act { wait_for_push } - - expect(page).to have_content('README.md') - expect(page).to have_content('This is a test project') - end - end - end -end -- cgit v1.2.1 From ed9bb8afa9687f48e03123f795aab047e667c062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 7 Aug 2018 17:06:31 +0200 Subject: Improve QA scenarios contexts & descriptions consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- qa/qa/scenario/test/instance.rb | 2 +- qa/qa/specs/features/api/1_manage/users_spec.rb | 26 ++-- .../login/log_into_gitlab_via_ldap_spec.rb | 28 ++-- .../login/log_into_mattermost_via_gitlab_spec.rb | 20 +-- .../1_manage/project/create_project_spec.rb | 32 +++-- .../1_manage/project/import_github_repo_spec.rb | 154 +++++++++++---------- .../1_manage/project/view_project_activity_spec.rb | 28 ++-- .../browser_ui/2_plan/issue/create_issue_spec.rb | 24 ++-- .../merge_request/create_merge_request_spec.rb | 58 ++++---- .../merge_merge_request_from_fork_spec.rb | 28 ++-- .../merge_request/rebase_merge_request_spec.rb | 74 +++++----- .../merge_request/squash_merge_request_spec.rb | 72 +++++----- .../browser_ui/3_create/repository/clone_spec.rb | 6 +- .../create_edit_delete_file_via_web_spec.rb | 102 +++++++------- .../3_create/repository/push_over_http_spec.rb | 6 +- .../repository/push_protected_branch_spec.rb | 94 +++++++------ .../wiki/create_edit_clone_push_wiki_spec.rb | 70 +++++----- .../pipeline/create_and_process_pipeline_spec.rb | 149 +++++++++----------- .../secret_variable/add_secret_variable_spec.rb | 32 +++-- .../6_release/deploy_key/add_deploy_key_spec.rb | 28 ++-- .../deploy_key/clone_using_deploy_key_spec.rb | 132 +++++++++--------- .../create_project_with_auto_devops_spec.rb | 100 ++++++------- .../create_group_with_mattermost_team_spec.rb | 24 ++-- qa/qa/specs/features/login/basic_spec.rb | 15 -- 24 files changed, 673 insertions(+), 631 deletions(-) delete mode 100644 qa/qa/specs/features/login/basic_spec.rb diff --git a/qa/qa/scenario/test/instance.rb b/qa/qa/scenario/test/instance.rb index e41c742376a..a2d503cc015 100644 --- a/qa/qa/scenario/test/instance.rb +++ b/qa/qa/scenario/test/instance.rb @@ -31,7 +31,7 @@ module QA if rspec_options.any? rspec_options else - ['--tag', self.class.focus.join(','), '--', ::File.expand_path('../../specs/features', __dir__)] + ['--', ::File.expand_path('../../specs/features', __dir__)] end end end diff --git a/qa/qa/specs/features/api/1_manage/users_spec.rb b/qa/qa/specs/features/api/1_manage/users_spec.rb index 3d25cca1e59..3e3c9e859aa 100644 --- a/qa/qa/specs/features/api/1_manage/users_spec.rb +++ b/qa/qa/specs/features/api/1_manage/users_spec.rb @@ -1,19 +1,21 @@ +# frozen_string_literal: true + module QA - describe 'API users' do - before(:context) do - @api_client = Runtime::API::Client.new(:gitlab) - end + context :manage do + describe 'Users API' do + before(:context) do + @api_client = Runtime::API::Client.new(:gitlab) + end - context 'when authenticated' do let(:request) { Runtime::API::Request.new(@api_client, '/users') } - it 'get list of users' do + it 'GET /users' do get request.url expect_status(200) end - it 'submit request with a valid user name' do + it 'GET /users/:username with a valid username' do get request.url, { params: { username: Runtime::User.username } } expect_status(200) @@ -22,20 +24,12 @@ module QA ) end - it 'submit request with an invalid user name' do + it 'GET /users/:username with an invalid username' do get request.url, { params: { username: SecureRandom.hex(10) } } expect_status(200) expect(json_body).to eq([]) end end - - it 'submit request with an invalid token' do - request = Runtime::API::Request.new(@api_client, '/users', private_token: 'invalid') - - get request.url - - expect_status(401) - end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb index de6111eea64..c9958917be9 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb @@ -1,18 +1,22 @@ +# frozen_string_literal: true + module QA - describe 'LDAP user login', :orchestrated, :ldap do - before do - Runtime::Env.user_type = 'ldap' - end + context :manage, :orchestrated, :ldap do + describe 'LDAP login' do + before do + Runtime::Env.user_type = 'ldap' + end - it 'user logs in using LDAP credentials' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } + it 'user logs into GitLab using LDAP credentials' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } - # TODO, since `Signed in successfully` message was removed - # this is the only way to tell if user is signed in correctly. - # - Page::Menu::Main.perform do |menu| - expect(menu).to have_personal_area + # TODO, since `Signed in successfully` message was removed + # this is the only way to tell if user is signed in correctly. + # + Page::Menu::Main.perform do |menu| + expect(menu).to have_personal_area + end end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb index 27f7d4c245f..6eda2c750d4 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb @@ -1,14 +1,18 @@ +# frozen_string_literal: true + module QA - describe 'logging in to Mattermost', :orchestrated, :mattermost do - it 'can use gitlab oauth' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) do - Page::Main::Login.act { sign_in_using_credentials } + context :manage, :orchestrated, :mattermost do + describe 'Mattermost login' do + it 'user logs into Mattermost using GitLab OAuth' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) do + Page::Main::Login.act { sign_in_using_credentials } - Runtime::Browser.visit(:mattermost, Page::Mattermost::Login) do - Page::Mattermost::Login.act { sign_in_using_oauth } + Runtime::Browser.visit(:mattermost, Page::Mattermost::Login) do + Page::Mattermost::Login.act { sign_in_using_oauth } - Page::Mattermost::Main.perform do |page| - expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/) + Page::Mattermost::Main.perform do |page| + expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/) + end end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb index 5e19e490778..bb1f3ab26d1 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb @@ -1,22 +1,26 @@ +# frozen_string_literal: true + module QA - describe 'create a new project', :smoke do - it 'user creates a new project' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } + context :manage, :smoke do + describe 'Project creation' do + it 'user creates a new project' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } - created_project = Factory::Resource::Project.fabricate! do |project| - project.name = 'awesome-project' - project.description = 'create awesome project test' - end + created_project = Factory::Resource::Project.fabricate! do |project| + project.name = 'awesome-project' + project.description = 'create awesome project test' + end - expect(created_project.name).to match /^awesome-project-\h{16}$/ + expect(created_project.name).to match /^awesome-project-\h{16}$/ - expect(page).to have_content( - /Project \S?awesome-project\S+ was successfully created/ - ) + expect(page).to have_content( + /Project \S?awesome-project\S+ was successfully created/ + ) - expect(page).to have_content('create awesome project test') - expect(page).to have_content('The repository for this project is empty') + expect(page).to have_content('create awesome project test') + expect(page).to have_content('The repository for this project is empty') + end end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb index 57695d2c726..2ef8de61441 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb @@ -1,106 +1,110 @@ +# frozen_string_literal: true + module QA - describe 'user imports a GitHub repo', :orchestrated, :github do - let(:imported_project) do - Factory::Resource::ProjectImportedFromGithub.fabricate! do |project| - project.name = 'imported-project' - project.personal_access_token = Runtime::Env.github_access_token - project.github_repository_path = 'gitlab-qa/test-project' + context :manage, :orchestrated, :github do + describe 'Project import from GitHub' do + let(:imported_project) do + Factory::Resource::ProjectImportedFromGithub.fabricate! do |project| + project.name = 'imported-project' + project.personal_access_token = Runtime::Env.github_access_token + project.github_repository_path = 'gitlab-qa/test-project' + end end - end - after do - # We need to delete the imported project because it's impossible to import - # the same GitHub project twice for a given user. - api_client = Runtime::API::Client.new(:gitlab) - delete_project_request = Runtime::API::Request.new(api_client, "/projects/#{CGI.escape("#{Runtime::Namespace.path}/#{imported_project.name}")}") - delete delete_project_request.url + after do + # We need to delete the imported project because it's impossible to import + # the same GitHub project twice for a given user. + api_client = Runtime::API::Client.new(:gitlab) + delete_project_request = Runtime::API::Request.new(api_client, "/projects/#{CGI.escape("#{Runtime::Namespace.path}/#{imported_project.name}")}") + delete delete_project_request.url - expect_status(202) - end + expect_status(202) + end - it 'user imports a GitHub repo' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } + it 'user imports a GitHub repo' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } - imported_project # import the project + imported_project # import the project - Page::Menu::Main.act { go_to_projects } - Page::Dashboard::Projects.perform do |dashboard| - dashboard.go_to_project(imported_project.name) - end + Page::Menu::Main.act { go_to_projects } + Page::Dashboard::Projects.perform do |dashboard| + dashboard.go_to_project(imported_project.name) + end - Page::Project::Show.act { wait_for_import } + Page::Project::Show.act { wait_for_import } - verify_repository_import - verify_issues_import - verify_merge_requests_import - verify_labels_import - verify_milestones_import - verify_wiki_import - end + verify_repository_import + verify_issues_import + verify_merge_requests_import + verify_labels_import + verify_milestones_import + verify_wiki_import + end - def verify_repository_import - expect(page).to have_content('This test project is used for automated GitHub import by GitLab QA.') - expect(page).to have_content(imported_project.name) - end + def verify_repository_import + expect(page).to have_content('This test project is used for automated GitHub import by GitLab QA.') + expect(page).to have_content(imported_project.name) + end - def verify_issues_import - Page::Menu::Side.act { click_issues } - expect(page).to have_content('This is a sample issue') + def verify_issues_import + Page::Menu::Side.act { click_issues } + expect(page).to have_content('This is a sample issue') - click_link 'This is a sample issue' + click_link 'This is a sample issue' - expect(page).to have_content('We should populate this project with issues, pull requests and wiki pages.') + expect(page).to have_content('We should populate this project with issues, pull requests and wiki pages.') - # Comments - expect(page).to have_content('This is a comment from @rymai.') + # Comments + expect(page).to have_content('This is a comment from @rymai.') - Page::Issuable::Sidebar.perform do |issuable| - expect(issuable).to have_label('enhancement') - expect(issuable).to have_label('help wanted') - expect(issuable).to have_label('good first issue') + Page::Issuable::Sidebar.perform do |issuable| + expect(issuable).to have_label('enhancement') + expect(issuable).to have_label('help wanted') + expect(issuable).to have_label('good first issue') + end end - end - def verify_merge_requests_import - Page::Menu::Side.act { click_merge_requests } - expect(page).to have_content('Improve README.md') + def verify_merge_requests_import + Page::Menu::Side.act { click_merge_requests } + expect(page).to have_content('Improve README.md') - click_link 'Improve README.md' + click_link 'Improve README.md' - expect(page).to have_content('This improves the README file a bit.') + expect(page).to have_content('This improves the README file a bit.') - # Review comment are not supported yet - expect(page).not_to have_content('Really nice change.') + # Review comment are not supported yet + expect(page).not_to have_content('Really nice change.') - # Comments - expect(page).to have_content('Nice work! This is a comment from @rymai.') + # Comments + expect(page).to have_content('Nice work! This is a comment from @rymai.') - # Diff comments - expect(page).to have_content('[Review comment] I like that!') - expect(page).to have_content('[Review comment] Nice blank line.') - expect(page).to have_content('[Single diff comment] Much better without this line!') + # Diff comments + expect(page).to have_content('[Review comment] I like that!') + expect(page).to have_content('[Review comment] Nice blank line.') + expect(page).to have_content('[Single diff comment] Much better without this line!') - Page::Issuable::Sidebar.perform do |issuable| - expect(issuable).to have_label('bug') - expect(issuable).to have_label('enhancement') + Page::Issuable::Sidebar.perform do |issuable| + expect(issuable).to have_label('bug') + expect(issuable).to have_label('enhancement') + end end - end - def verify_labels_import - # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19228 - # to build upon it. - end + def verify_labels_import + # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19228 + # to build upon it. + end - def verify_milestones_import - # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18727 - # to build upon it. - end + def verify_milestones_import + # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18727 + # to build upon it. + end - def verify_wiki_import - Page::Menu::Side.act { click_wiki } + def verify_wiki_import + Page::Menu::Side.act { click_wiki } - expect(page).to have_content('Welcome to the test-project wiki!') + expect(page).to have_content('Welcome to the test-project wiki!') + end end end end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb index c7ce8dfdcc6..34bb6f1c197 100644 --- a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb +++ b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb @@ -1,20 +1,24 @@ +# frozen_string_literal: true + module QA - describe 'activity page' do - it 'push creates an event in the activity page' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } + context :manage do + describe 'Project activity' do + it 'user creates an event in the activity page upon Git push' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } - Factory::Repository::ProjectPush.fabricate! do |push| - push.file_name = 'README.md' - push.file_content = '# This is a test project' - push.commit_message = 'Add README.md' - end + Factory::Repository::ProjectPush.fabricate! do |push| + push.file_name = 'README.md' + push.file_content = '# This is a test project' + push.commit_message = 'Add README.md' + end - Page::Menu::Side.act { go_to_activity } + Page::Menu::Side.act { go_to_activity } - Page::Project::Activity.act { go_to_push_events } + Page::Project::Activity.act { go_to_push_events } - expect(page).to have_content('pushed new branch master') + expect(page).to have_content('pushed new branch master') + end end end end diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb index 793e7db87cb..dd1be935220 100644 --- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb @@ -1,18 +1,22 @@ +# frozen_string_literal: true + module QA - describe 'creates issue', :smoke do - let(:issue_title) { 'issue title' } + context :plan, :smoke do + describe 'Issue creation' do + let(:issue_title) { 'issue title' } - it 'user creates issue' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } + it 'user creates an issue' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } - Factory::Resource::Issue.fabricate! do |issue| - issue.title = issue_title - end + Factory::Resource::Issue.fabricate! do |issue| + issue.title = issue_title + end - Page::Menu::Side.act { click_issues } + Page::Menu::Side.act { click_issues } - expect(page).to have_content(issue_title) + expect(page).to have_content(issue_title) + end end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb index 71e79956b85..bcf55a02a61 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb @@ -1,31 +1,35 @@ -module QA - describe 'creates a merge request with milestone' do - it 'user creates a new merge request' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - current_project = Factory::Resource::Project.fabricate! do |project| - project.name = 'project-with-merge-request-and-milestone' - end - - current_milestone = Factory::Resource::ProjectMilestone.fabricate! do |milestone| - milestone.title = 'unique-milestone' - milestone.project = current_project - end - - Factory::Resource::MergeRequest.fabricate! do |merge_request| - merge_request.title = 'This is a merge request with a milestone' - merge_request.description = 'Great feature with milestone' - merge_request.project = current_project - merge_request.milestone = current_milestone - end - - expect(page).to have_content('This is a merge request with a milestone') - expect(page).to have_content('Great feature with milestone') - expect(page).to have_content(/Opened [\w\s]+ ago/) +# frozen_string_literal: true - Page::Issuable::Sidebar.perform do |sidebar| - expect(sidebar).to have_milestone(current_milestone.title) +module QA + context :create do + describe 'Merge request creation' do + it 'user creates a new merge request' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + current_project = Factory::Resource::Project.fabricate! do |project| + project.name = 'project-with-merge-request-and-milestone' + end + + current_milestone = Factory::Resource::ProjectMilestone.fabricate! do |milestone| + milestone.title = 'unique-milestone' + milestone.project = current_project + end + + Factory::Resource::MergeRequest.fabricate! do |merge_request| + merge_request.title = 'This is a merge request with a milestone' + merge_request.description = 'Great feature with milestone' + merge_request.project = current_project + merge_request.milestone = current_milestone + end + + expect(page).to have_content('This is a merge request with a milestone') + expect(page).to have_content('Great feature with milestone') + expect(page).to have_content(/Opened [\w\s]+ ago/) + + Page::Issuable::Sidebar.perform do |sidebar| + expect(sidebar).to have_milestone(current_milestone.title) + end end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb index 280978bb950..407a15800ab 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb @@ -1,21 +1,25 @@ +# frozen_string_literal: true + module QA - describe 'Project fork' do - it 'can submit merge requests to upstream master' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } + context :create do + describe 'Merge request creation from fork' do + it 'user forks a project, submits a merge request and maintainer merges it' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } - merge_request = Factory::Resource::MergeRequestFromFork.fabricate! do |merge_request| - merge_request.fork_branch = 'feature-branch' - end + merge_request = Factory::Resource::MergeRequestFromFork.fabricate! do |merge_request| + merge_request.fork_branch = 'feature-branch' + end - Page::Menu::Main.perform { |main| main.sign_out } - Page::Main::Login.perform { |login| login.sign_in_using_credentials } + Page::Menu::Main.perform { |main| main.sign_out } + Page::Main::Login.perform { |login| login.sign_in_using_credentials } - merge_request.visit! + merge_request.visit! - Page::MergeRequest::Show.perform { |show| show.merge! } + Page::MergeRequest::Show.perform { |show| show.merge! } - expect(page).to have_content('The changes were merged') + expect(page).to have_content('The changes were merged') + end end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb index c36d28e4237..ddcbc94b1b1 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb @@ -1,38 +1,44 @@ -module QA - describe 'merge request rebase' do - it 'rebases source branch of merge request' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - project = Factory::Resource::Project.fabricate! do |project| - project.name = "only-fast-forward" - end - - Page::Menu::Side.act { go_to_settings } - Page::Project::Settings::MergeRequest.act { enable_ff_only } - - merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| - merge_request.project = project - merge_request.title = 'Needs rebasing' - end +# frozen_string_literal: true - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.file_name = "other.txt" - push.file_content = "New file added!" - end - - merge_request.visit! - - Page::MergeRequest::Show.perform do |merge_request| - expect(merge_request).to have_content('Needs rebasing') - expect(merge_request).not_to be_fast_forward_possible - expect(merge_request).not_to have_merge_button - - merge_request.rebase! - - expect(merge_request).to have_merge_button - expect(merge_request.fast_forward_possible?).to be_truthy +module QA + context :create do + describe 'Merge request rebasing' do + it 'user rebases source branch of merge request' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + project = Factory::Resource::Project.fabricate! do |project| + project.name = "only-fast-forward" + end + + Page::Menu::Side.act { go_to_settings } + Page::Project::Settings::MergeRequest.act { enable_ff_only } + + merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| + merge_request.project = project + merge_request.title = 'Needs rebasing' + end + + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.file_name = "other.txt" + push.file_content = "New file added!" + push.branch_name = "master" + push.new_branch = false + end + + merge_request.visit! + + Page::MergeRequest::Show.perform do |merge_request| + expect(merge_request).to have_content('Needs rebasing') + expect(merge_request).not_to be_fast_forward_possible + expect(merge_request).not_to have_merge_button + + merge_request.rebase! + + expect(merge_request).to have_merge_button + expect(merge_request.fast_forward_possible?).to be_truthy + end end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb index 3ecc36a5ae1..b5b8855a35d 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb @@ -1,48 +1,52 @@ -module QA - describe 'merge request squash commits' do - it 'when squash commits is marked before merge' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } +# frozen_string_literal: true - project = Factory::Resource::Project.fabricate! do |project| - project.name = "squash-before-merge" - end +module QA + context :create do + describe 'Merge request squashing' do + it 'user squashes commits while merging' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + project = Factory::Resource::Project.fabricate! do |project| + project.name = "squash-before-merge" + end - merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| - merge_request.project = project - merge_request.title = 'Squashing commits' - end + merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| + merge_request.project = project + merge_request.title = 'Squashing commits' + end - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.commit_message = 'to be squashed' - push.branch_name = merge_request.source_branch - push.new_branch = false - push.file_name = 'other.txt' - push.file_content = "Test with unicode characters ❤✓€❄" - end + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.commit_message = 'to be squashed' + push.branch_name = merge_request.source_branch + push.new_branch = false + push.file_name = 'other.txt' + push.file_content = "Test with unicode characters ❤✓€❄" + end - merge_request.visit! + merge_request.visit! - expect(page).to have_text('to be squashed') + expect(page).to have_text('to be squashed') - Page::MergeRequest::Show.perform do |merge_request_page| - merge_request_page.mark_to_squash - merge_request_page.merge! + Page::MergeRequest::Show.perform do |merge_request_page| + merge_request_page.mark_to_squash + merge_request_page.merge! - merge_request.project.visit! + merge_request.project.visit! - Git::Repository.perform do |repository| - repository.uri = Page::Project::Show.act do - choose_repository_clone_http - repository_location.uri - end + Git::Repository.perform do |repository| + repository.uri = Page::Project::Show.act do + choose_repository_clone_http + repository_location.uri + end - repository.use_default_credentials + repository.use_default_credentials - repository.act { clone } + repository.act { clone } - expect(repository.commits.size).to eq 3 + expect(repository.commits.size).to eq 3 + end end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb index 8b0613c5f78..b19bdd950fa 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + module QA - describe 'clone code from the repository' do - context 'with regular account over http' do + context :create do + describe 'Git clone over HTTP' do let(:location) do Page::Project::Show.act do choose_repository_clone_http diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb index 5659784cd5c..f18655442c1 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb @@ -1,54 +1,58 @@ -module QA - describe 'File Functionality', :core do - it 'lets a user create, edit and delete a file via WebUI' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - # Create - file_name = 'QA Test - File name' - file_content = 'QA Test - File content' - commit_message_for_create = 'QA Test - Create new file' - - Factory::Resource::File.fabricate! do |file| - file.name = file_name - file.content = file_content - file.commit_message = commit_message_for_create - end - - expect(page).to have_content('The file has been successfully created.') - expect(page).to have_content(file_name) - expect(page).to have_content(file_content) - expect(page).to have_content(commit_message_for_create) +# frozen_string_literal: true - # Edit - updated_file_content = 'QA Test - Updated file content' - commit_message_for_update = 'QA Test - Update file' - - Page::File::Show.act { click_edit } - - Page::File::Form.act do - remove_content - add_content(updated_file_content) - add_commit_message(commit_message_for_update) - commit_changes - end - - expect(page).to have_content('Your changes have been successfully committed.') - expect(page).to have_content(updated_file_content) - expect(page).to have_content(commit_message_for_update) - - # Delete - commit_message_for_delete = 'QA Test - Delete file' - - Page::File::Show.act do - click_delete - add_commit_message(commit_message_for_delete) - click_delete_file +module QA + context :create, :core do + describe 'Files management' do + it 'user creates, edits and deletes a file via the Web' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + # Create + file_name = 'QA Test - File name' + file_content = 'QA Test - File content' + commit_message_for_create = 'QA Test - Create new file' + + Factory::Resource::File.fabricate! do |file| + file.name = file_name + file.content = file_content + file.commit_message = commit_message_for_create + end + + expect(page).to have_content('The file has been successfully created.') + expect(page).to have_content(file_name) + expect(page).to have_content(file_content) + expect(page).to have_content(commit_message_for_create) + + # Edit + updated_file_content = 'QA Test - Updated file content' + commit_message_for_update = 'QA Test - Update file' + + Page::File::Show.act { click_edit } + + Page::File::Form.act do + remove_content + add_content(updated_file_content) + add_commit_message(commit_message_for_update) + commit_changes + end + + expect(page).to have_content('Your changes have been successfully committed.') + expect(page).to have_content(updated_file_content) + expect(page).to have_content(commit_message_for_update) + + # Delete + commit_message_for_delete = 'QA Test - Delete file' + + Page::File::Show.act do + click_delete + add_commit_message(commit_message_for_delete) + click_delete_file + end + + expect(page).to have_content('The file has been successfully deleted.') + expect(page).to have_content(commit_message_for_delete) + expect(page).to have_no_content(file_name) end - - expect(page).to have_content('The file has been successfully deleted.') - expect(page).to have_content(commit_message_for_delete) - expect(page).to have_no_content(file_name) end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb index 1e89942e932..40dfd138a1b 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + module QA - describe 'push code to repository' do - context 'with regular account over http' do + context :create do + describe 'Git push over HTTP' do it 'user pushes code to the repository' do Runtime::Browser.visit(:gitlab, Page::Main::Login) Page::Main::Login.act { sign_in_using_credentials } diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb index aa23145478d..1d9cc33080d 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb @@ -1,65 +1,69 @@ +# frozen_string_literal: true + module QA - describe 'branch protection support' do - let(:branch_name) { 'protected-branch' } - let(:commit_message) { 'Protected push commit message' } - let(:project) do - Factory::Resource::Project.fabricate! do |resource| - resource.name = 'protected-branch-project' + context :create do + describe 'Protected branch support' do + let(:branch_name) { 'protected-branch' } + let(:commit_message) { 'Protected push commit message' } + let(:project) do + Factory::Resource::Project.fabricate! do |resource| + resource.name = 'protected-branch-project' + end end - end - before do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - end + before do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + end - after do - # We need to clear localStorage because we're using it for the dropdown, - # and capybara doesn't do this for us. - # https://github.com/teamcapybara/capybara/issues/1702 - Capybara.execute_script 'localStorage.clear()' - end + after do + # We need to clear localStorage because we're using it for the dropdown, + # and capybara doesn't do this for us. + # https://github.com/teamcapybara/capybara/issues/1702 + Capybara.execute_script 'localStorage.clear()' + end - context 'when developers and maintainers are allowed to push to a protected branch' do - it 'user with push rights successfully pushes to the protected branch' do - create_protected_branch(allow_to_push: true) + context 'when developers and maintainers are allowed to push to a protected branch' do + it 'user with push rights successfully pushes to the protected branch' do + create_protected_branch(allow_to_push: true) - push = push_new_file(branch_name) + push = push_new_file(branch_name) - expect(push.output).to match(/remote: To create a merge request for protected-branch, visit/) + expect(push.output).to match(/remote: To create a merge request for protected-branch, visit/) + end end - end - context 'when developers and maintainers are not allowed to push to a protected branch' do - it 'user without push rights fails to push to the protected branch' do - create_protected_branch(allow_to_push: false) + context 'when developers and maintainers are not allowed to push to a protected branch' do + it 'user without push rights fails to push to the protected branch' do + create_protected_branch(allow_to_push: false) - push = push_new_file(branch_name) + push = push_new_file(branch_name) - expect(push.output) + expect(push.output) .to match(/remote\: GitLab\: You are not allowed to push code to protected branches on this project/) - expect(push.output) + expect(push.output) .to match(/\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/) + end end - end - def create_protected_branch(allow_to_push:) - Factory::Resource::Branch.fabricate! do |resource| - resource.branch_name = branch_name - resource.project = project - resource.allow_to_push = allow_to_push - resource.protected = true + def create_protected_branch(allow_to_push:) + Factory::Resource::Branch.fabricate! do |resource| + resource.branch_name = branch_name + resource.project = project + resource.allow_to_push = allow_to_push + resource.protected = true + end end - end - def push_new_file(branch) - Factory::Repository::ProjectPush.fabricate! do |resource| - resource.project = project - resource.file_name = 'new_file.md' - resource.file_content = '# This is a new file' - resource.commit_message = 'Add new_file.md' - resource.branch_name = branch_name - resource.new_branch = false + def push_new_file(branch) + Factory::Repository::ProjectPush.fabricate! do |resource| + resource.project = project + resource.file_name = 'new_file.md' + resource.file_content = '# This is a new file' + resource.commit_message = 'Add new_file.md' + resource.branch_name = branch_name + resource.new_branch = false + end end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb index 9af2dbd1264..8009b9e8609 100644 --- a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb @@ -1,45 +1,49 @@ -module QA - describe 'Wiki Functionality' do - def login - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - end +# frozen_string_literal: true - def validate_content(content) - expect(page).to have_content('Wiki was successfully updated') - expect(page).to have_content(/#{content}/) - end +module QA + context :create do + describe 'Wiki management' do + def login + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + end - before do - login - end + def validate_content(content) + expect(page).to have_content('Wiki was successfully updated') + expect(page).to have_content(/#{content}/) + end - it 'User creates, edits, clones, and pushes to the wiki' do - wiki = Factory::Resource::Wiki.fabricate! do |resource| - resource.title = 'Home' - resource.content = '# My First Wiki Content' - resource.message = 'Update home' + before do + login end - validate_content('My First Wiki Content') + it 'user creates, edits, clones, and pushes to the wiki' do + wiki = Factory::Resource::Wiki.fabricate! do |resource| + resource.title = 'Home' + resource.content = '# My First Wiki Content' + resource.message = 'Update home' + end - Page::Project::Wiki::Edit.act { go_to_edit_page } - Page::Project::Wiki::New.perform do |page| - page.set_content("My Second Wiki Content") - page.save_changes - end + validate_content('My First Wiki Content') - validate_content('My Second Wiki Content') + Page::Project::Wiki::Edit.act { go_to_edit_page } + Page::Project::Wiki::New.perform do |page| + page.set_content("My Second Wiki Content") + page.save_changes + end - Factory::Repository::WikiPush.fabricate! do |push| - push.wiki = wiki - push.file_name = 'Home.md' - push.file_content = '# My Third Wiki Content' - push.commit_message = 'Update Home.md' - end - Page::Menu::Side.act { click_wiki } + validate_content('My Second Wiki Content') - expect(page).to have_content('My Third Wiki Content') + Factory::Repository::WikiPush.fabricate! do |push| + push.wiki = wiki + push.file_name = 'Home.md' + push.file_content = '# My Third Wiki Content' + push.commit_message = 'Update Home.md' + end + Page::Menu::Side.act { click_wiki } + + expect(page).to have_content('My Third Wiki Content') + end end end end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb index 6c6b4e80626..cdfe9b90e15 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb @@ -1,101 +1,86 @@ -module QA - describe 'CI/CD Pipelines', :orchestrated, :docker do - let(:executor) { "qa-runner-#{Time.now.to_i}" } - - after do - Service::Runner.new(executor).remove! - end +# frozen_string_literal: true - it 'user registers a new specific runner' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } +module QA + context :verify, :orchestrated, :docker do + describe 'Pipeline creation and processing' do + let(:executor) { "qa-runner-#{Time.now.to_i}" } - Factory::Resource::Runner.fabricate! do |runner| - runner.name = executor + after do + Service::Runner.new(executor).remove! end - Page::Project::Settings::CICD.perform do |settings| - sleep 5 # Runner should register within 5 seconds - settings.refresh + it 'users creates a pipeline which gets processed' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } - settings.expand_runners_settings do |page| - expect(page).to have_content(executor) - expect(page).to have_online_runner + project = Factory::Resource::Project.fabricate! do |project| + project.name = 'project-with-pipelines' + project.description = 'Project with CI/CD Pipelines.' end - end - end - - it 'users creates a new pipeline' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - project = Factory::Resource::Project.fabricate! do |project| - project.name = 'project-with-pipelines' - project.description = 'Project with CI/CD Pipelines.' - end - - Factory::Resource::Runner.fabricate! do |runner| - runner.project = project - runner.name = executor - runner.tags = %w[qa test] - end + Factory::Resource::Runner.fabricate! do |runner| + runner.project = project + runner.name = executor + runner.tags = %w[qa test] + end - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.file_name = '.gitlab-ci.yml' - push.commit_message = 'Add .gitlab-ci.yml' - push.file_content = <<~EOF - test-success: - tags: - - qa - - test - script: echo 'OK' - - test-failure: - tags: - - qa - - test - script: - - echo 'FAILURE' - - exit 1 - - test-tags: - tags: - - qa - - docker - script: echo 'NOOP' - - test-artifacts: - tags: - - qa - - test - script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt - artifacts: - paths: + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.file_name = '.gitlab-ci.yml' + push.commit_message = 'Add .gitlab-ci.yml' + push.file_content = <<~EOF + test-success: + tags: + - qa + - test + script: echo 'OK' + + test-failure: + tags: + - qa + - test + script: + - echo 'FAILURE' + - exit 1 + + test-tags: + tags: + - qa + - docker + script: echo 'NOOP' + + test-artifacts: + tags: + - qa + - test + script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt + artifacts: + paths: - my-artifacts/ - EOF - end + EOF + end - Page::Project::Show.act { wait_for_push } + Page::Project::Show.act { wait_for_push } - expect(page).to have_content('Add .gitlab-ci.yml') + expect(page).to have_content('Add .gitlab-ci.yml') - Page::Menu::Side.act { click_ci_cd_pipelines } + Page::Menu::Side.act { click_ci_cd_pipelines } - expect(page).to have_content('All 1') - expect(page).to have_content('Add .gitlab-ci.yml') + expect(page).to have_content('All 1') + expect(page).to have_content('Add .gitlab-ci.yml') - puts 'Waiting for the runner to process the pipeline' - sleep 15 # Runner should process all jobs within 15 seconds. + puts 'Waiting for the runner to process the pipeline' + sleep 15 # Runner should process all jobs within 15 seconds. - Page::Project::Pipeline::Index.act { go_to_latest_pipeline } + Page::Project::Pipeline::Index.act { go_to_latest_pipeline } - Page::Project::Pipeline::Show.perform do |pipeline| - expect(pipeline).to be_running - expect(pipeline).to have_build('test-success', status: :success) - expect(pipeline).to have_build('test-failure', status: :failed) - expect(pipeline).to have_build('test-tags', status: :pending) - expect(pipeline).to have_build('test-artifacts', status: :success) + Page::Project::Pipeline::Show.perform do |pipeline| + expect(pipeline).to be_running + expect(pipeline).to have_build('test-success', status: :success) + expect(pipeline).to have_build('test-failure', status: :failed) + expect(pipeline).to have_build('test-tags', status: :pending) + expect(pipeline).to have_build('test-artifacts', status: :success) + end end end end diff --git a/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb index 04d9fe488e2..08a87df5837 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb @@ -1,22 +1,26 @@ +# frozen_string_literal: true + module QA - describe 'secret variables support' do - it 'user adds a secret variable' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } + context :verify do + describe 'Secret variable support' do + it 'user adds a secret variable' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } - Factory::Resource::SecretVariable.fabricate! do |resource| - resource.key = 'VARIABLE_KEY' - resource.value = 'some secret variable' - end + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.key = 'VARIABLE_KEY' + resource.value = 'some secret variable' + end - Page::Project::Settings::CICD.perform do |settings| - settings.expand_secret_variables do |page| - expect(page).to have_field(with: 'VARIABLE_KEY') - expect(page).not_to have_field(with: 'some secret variable') + Page::Project::Settings::CICD.perform do |settings| + settings.expand_secret_variables do |page| + expect(page).to have_field(with: 'VARIABLE_KEY') + expect(page).not_to have_field(with: 'some secret variable') - page.reveal_variables + page.reveal_variables - expect(page).to have_field(with: 'some secret variable') + expect(page).to have_field(with: 'some secret variable') + end end end end diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb index 24f9f4c77f8..17dfa887434 100644 --- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb @@ -1,19 +1,23 @@ +# frozen_string_literal: true + module QA - describe 'deploy keys support' do - it 'user adds a deploy key' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } + context :release do + describe 'Deploy key creation' do + it 'user adds a deploy key' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } - key = Runtime::Key::RSA.new - deploy_key_title = 'deploy key title' - deploy_key_value = key.public_key + key = Runtime::Key::RSA.new + deploy_key_title = 'deploy key title' + deploy_key_value = key.public_key - deploy_key = Factory::Resource::DeployKey.fabricate! do |resource| - resource.title = deploy_key_title - resource.key = deploy_key_value - end + deploy_key = Factory::Resource::DeployKey.fabricate! do |resource| + resource.title = deploy_key_title + resource.key = deploy_key_value + end - expect(deploy_key.fingerprint).to eq(key.fingerprint) + expect(deploy_key.fingerprint).to eq(key.fingerprint) + end end end end diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb index 1d099508c24..8352d13b06d 100644 --- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb @@ -1,64 +1,67 @@ +# frozen_string_literal: true + require 'digest/sha1' module QA - describe 'cloning code using a deploy key', :docker do - def login - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - end + context :release, :docker do + describe 'Git clone using a deploy key' do + def login + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + end - before(:all) do - login + before(:all) do + login - @runner_name = "qa-runner-#{Time.now.to_i}" + @runner_name = "qa-runner-#{Time.now.to_i}" - @project = Factory::Resource::Project.fabricate! do |resource| - resource.name = 'deploy-key-clone-project' - end + @project = Factory::Resource::Project.fabricate! do |resource| + resource.name = 'deploy-key-clone-project' + end - @repository_location = @project.repository_ssh_location + @repository_location = @project.repository_ssh_location - Factory::Resource::Runner.fabricate! do |resource| - resource.project = @project - resource.name = @runner_name - resource.tags = %w[qa docker] - resource.image = 'gitlab/gitlab-runner:ubuntu' - end + Factory::Resource::Runner.fabricate! do |resource| + resource.project = @project + resource.name = @runner_name + resource.tags = %w[qa docker] + resource.image = 'gitlab/gitlab-runner:ubuntu' + end - Page::Menu::Main.act { sign_out } - end + Page::Menu::Main.act { sign_out } + end - after(:all) do - Service::Runner.new(@runner_name).remove! - end + after(:all) do + Service::Runner.new(@runner_name).remove! + end - keys = [ - [Runtime::Key::RSA, 8192], - [Runtime::Key::ECDSA, 521], - [Runtime::Key::ED25519] - ] + keys = [ + [Runtime::Key::RSA, 8192], + [Runtime::Key::ECDSA, 521], + [Runtime::Key::ED25519] + ] - keys.each do |(key_class, bits)| - it "user sets up a deploy key with #{key_class}(#{bits}) to clone code using pipelines" do - key = key_class.new(*bits) + keys.each do |(key_class, bits)| + it "user sets up a deploy key with #{key_class}(#{bits}) to clone code using pipelines" do + key = key_class.new(*bits) - login + login - Factory::Resource::DeployKey.fabricate! do |resource| - resource.project = @project - resource.title = "deploy key #{key.name}(#{key.bits})" - resource.key = key.public_key - end + Factory::Resource::DeployKey.fabricate! do |resource| + resource.project = @project + resource.title = "deploy key #{key.name}(#{key.bits})" + resource.key = key.public_key + end - deploy_key_name = "DEPLOY_KEY_#{key.name}_#{key.bits}" + deploy_key_name = "DEPLOY_KEY_#{key.name}_#{key.bits}" - Factory::Resource::SecretVariable.fabricate! do |resource| - resource.project = @project - resource.key = deploy_key_name - resource.value = key.private_key - end + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.project = @project + resource.key = deploy_key_name + resource.value = key.private_key + end - gitlab_ci = <<~YAML + gitlab_ci = <<~YAML cat-config: script: - mkdir -p ~/.ssh @@ -73,31 +76,32 @@ module QA tags: - qa - docker - YAML + YAML + + Factory::Repository::ProjectPush.fabricate! do |resource| + resource.project = @project + resource.file_name = '.gitlab-ci.yml' + resource.commit_message = 'Add .gitlab-ci.yml' + resource.file_content = gitlab_ci + resource.branch_name = deploy_key_name + resource.new_branch = true + end - Factory::Repository::ProjectPush.fabricate! do |resource| - resource.project = @project - resource.file_name = '.gitlab-ci.yml' - resource.commit_message = 'Add .gitlab-ci.yml' - resource.file_content = gitlab_ci - resource.branch_name = deploy_key_name - resource.new_branch = true - end + sha1sum = Digest::SHA1.hexdigest(gitlab_ci) - sha1sum = Digest::SHA1.hexdigest(gitlab_ci) + Page::Project::Show.act { wait_for_push } + Page::Menu::Side.act { click_ci_cd_pipelines } + Page::Project::Pipeline::Index.act { go_to_latest_pipeline } + Page::Project::Pipeline::Show.act { go_to_first_job } - Page::Project::Show.act { wait_for_push } - Page::Menu::Side.act { click_ci_cd_pipelines } - Page::Project::Pipeline::Index.act { go_to_latest_pipeline } - Page::Project::Pipeline::Show.act { go_to_first_job } + Page::Project::Job::Show.perform do |job| + job.wait(reload: false) do + job.completed? && !job.trace_loading? + end - Page::Project::Job::Show.perform do |job| - job.wait(reload: false) do - job.completed? && !job.trace_loading? + expect(job.passed?).to be_truthy, "Job status did not become \"passed\"." + expect(job.output).to include(sha1sum) end - - expect(job.passed?).to be_truthy, "Job status did not become \"passed\"." - expect(job.output).to include(sha1sum) end end end diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb index 248669b6046..dd24e8ffba5 100644 --- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb +++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb @@ -1,63 +1,67 @@ +# frozen_string_literal: true + require 'pathname' module QA - describe 'Auto Devops', :orchestrated, :kubernetes do - after do - @cluster&.remove! - end + context :configure, :orchestrated, :kubernetes do + describe 'Auto DevOps support' do + after do + @cluster&.remove! + end - it 'user creates a new project and runs auto devops' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } + it 'user creates a new project and runs auto devops' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } - project = Factory::Resource::Project.fabricate! do |p| - p.name = 'project-with-autodevops' - p.description = 'Project with Auto Devops' - end + project = Factory::Resource::Project.fabricate! do |p| + p.name = 'project-with-autodevops' + p.description = 'Project with Auto Devops' + end - # Disable code_quality check in Auto DevOps pipeline as it takes - # too long and times out the test - Factory::Resource::SecretVariable.fabricate! do |resource| - resource.key = 'CODE_QUALITY_DISABLED' - resource.value = '1' - end + # Disable code_quality check in Auto DevOps pipeline as it takes + # too long and times out the test + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.key = 'CODE_QUALITY_DISABLED' + resource.value = '1' + end - # Create Auto Devops compatible repo - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.directory = Pathname - .new(__dir__) - .join('../../../fixtures/auto_devops_rack') - push.commit_message = 'Create Auto DevOps compatible rack application' - end + # Create Auto Devops compatible repo + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.directory = Pathname + .new(__dir__) + .join('../../../fixtures/auto_devops_rack') + push.commit_message = 'Create Auto DevOps compatible rack application' + end - Page::Project::Show.act { wait_for_push } + Page::Project::Show.act { wait_for_push } - # Create and connect K8s cluster - @cluster = Service::KubernetesCluster.new.create! - kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster| - cluster.project = project - cluster.cluster = @cluster - cluster.install_helm_tiller = true - cluster.install_ingress = true - cluster.install_prometheus = true - cluster.install_runner = true - end + # Create and connect K8s cluster + @cluster = Service::KubernetesCluster.new.create! + kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster| + cluster.project = project + cluster.cluster = @cluster + cluster.install_helm_tiller = true + cluster.install_ingress = true + cluster.install_prometheus = true + cluster.install_runner = true + end - project.visit! - Page::Menu::Side.act { click_ci_cd_settings } - Page::Project::Settings::CICD.perform do |p| - p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io") - end + project.visit! + Page::Menu::Side.act { click_ci_cd_settings } + Page::Project::Settings::CICD.perform do |p| + p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io") + end - project.visit! - Page::Menu::Side.act { click_ci_cd_pipelines } - Page::Project::Pipeline::Index.act { go_to_latest_pipeline } + project.visit! + Page::Menu::Side.act { click_ci_cd_pipelines } + Page::Project::Pipeline::Index.act { go_to_latest_pipeline } - Page::Project::Pipeline::Show.perform do |pipeline| - expect(pipeline).to have_build('build', status: :success, wait: 600) - expect(pipeline).to have_build('test', status: :success, wait: 600) - expect(pipeline).to have_build('production', status: :success, wait: 1200) + Page::Project::Pipeline::Show.perform do |pipeline| + expect(pipeline).to have_build('build', status: :success, wait: 600) + expect(pipeline).to have_build('test', status: :success, wait: 600) + expect(pipeline).to have_build('production', status: :success, wait: 1200) + end end end end diff --git a/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb index 097e1713aef..6ffdc55538a 100644 --- a/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb +++ b/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb @@ -1,16 +1,20 @@ +# frozen_string_literal: true + module QA - describe 'create a new group', :orchestrated, :mattermost do - it 'creating a group with a mattermost team' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - Page::Menu::Main.act { go_to_groups } + context :configure, :orchestrated, :mattermost do + describe 'Mattermost support' do + it 'user creates a group with a mattermost team' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + Page::Menu::Main.act { go_to_groups } - Page::Dashboard::Groups.perform do |page| - page.go_to_new_group + Page::Dashboard::Groups.perform do |page| + page.go_to_new_group - expect(page).to have_content( - /Create a Mattermost team for this group/ - ) + expect(page).to have_content( + /Create a Mattermost team for this group/ + ) + end end end end diff --git a/qa/qa/specs/features/login/basic_spec.rb b/qa/qa/specs/features/login/basic_spec.rb deleted file mode 100644 index f866466c7bf..00000000000 --- a/qa/qa/specs/features/login/basic_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -module QA - describe 'basic user login', :smoke do - it 'user logs in using basic credentials' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - # TODO, since `Signed in successfully` message was removed - # this is the only way to tell if user is signed in correctly. - # - Page::Menu::Main.perform do |menu| - expect(menu).to have_personal_area - end - end - end -end -- cgit v1.2.1 From 81960cba69dbe4c4a0e303127a3fa4c0199cf6c4 Mon Sep 17 00:00:00 2001 From: GitLab Release Tools Bot Date: Tue, 28 Aug 2018 16:04:50 +0000 Subject: Update CHANGELOG.md for 11.2.3 [ci skip] --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea753515299..ab4c625483e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 11.2.3 (2018-08-28) + +- No changes. + ## 11.2.2 (2018-08-27) ### Security (3 changes) -- cgit v1.2.1 From b1992a92f11056157bc854be538074482b72ee20 Mon Sep 17 00:00:00 2001 From: GitLab Release Tools Bot Date: Tue, 28 Aug 2018 16:05:28 +0000 Subject: Update CHANGELOG.md for 11.1.6 [ci skip] --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab4c625483e..5e022b7e52b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -267,6 +267,10 @@ entry. - Moves help_popover component to a common location. +## 11.1.6 (2018-08-28) + +- No changes. + ## 11.1.5 (2018-08-27) ### Security (3 changes) -- cgit v1.2.1 From ec40b36905d0a71edb4bfae592018b6ae580a492 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 9 Aug 2018 12:05:13 +0100 Subject: Removes
sent from backend on tooltips in jobs When backend sends HTML it requires frontend to append it to the DOM causing XSS vulnerabilities. By removing the `
` we avoid those vulnerabilities --- .../components/graph/dropdown_job_component.vue | 3 +-- .../pipelines/components/graph/job_component.vue | 5 +---- app/views/ci/status/_dropdown_graph_badge.html.haml | 4 ++-- app/views/projects/jobs/_sidebar.html.haml | 2 +- lib/gitlab/ci/status/build/failed.rb | 2 +- spec/features/projects/jobs/user_browses_job_spec.rb | 4 ++-- .../features/projects/jobs/user_browses_jobs_spec.rb | 2 +- spec/features/projects/pipelines/pipeline_spec.rb | 4 ++-- spec/features/projects/pipelines/pipelines_spec.rb | 2 +- .../pipelines/graph/dropdown_job_component_spec.js | 8 -------- .../pipelines/graph/job_component_spec.js | 20 -------------------- spec/lib/gitlab/ci/status/build/factory_spec.rb | 2 +- .../gitlab/ci/status/build/failed_allowed_spec.rb | 4 ++-- spec/lib/gitlab/ci/status/build/failed_spec.rb | 4 ++-- spec/lib/gitlab/ci/status/build/retried_spec.rb | 2 +- spec/presenters/ci/build_presenter_spec.rb | 12 ++++++------ spec/serializers/build_serializer_spec.rb | 2 +- spec/serializers/job_entity_spec.rb | 4 ++-- 18 files changed, 27 insertions(+), 59 deletions(-) diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue index 8487c8036ee..2ad66f4fe86 100644 --- a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue @@ -1,6 +1,5 @@