From 859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 18 Feb 2021 10:34:06 +0000 Subject: Add latest changes from gitlab-org/gitlab@13-9-stable-ee --- .../projects/pages/user_adds_domain_spec.rb | 185 +++++++++++++++++++ .../pages/user_edits_lets_encrypt_settings_spec.rb | 167 +++++++++++++++++ .../projects/pages/user_edits_settings_spec.rb | 201 +++++++++++++++++++++ 3 files changed, 553 insertions(+) create mode 100644 spec/features/projects/pages/user_adds_domain_spec.rb create mode 100644 spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb create mode 100644 spec/features/projects/pages/user_edits_settings_spec.rb (limited to 'spec/features/projects/pages') diff --git a/spec/features/projects/pages/user_adds_domain_spec.rb b/spec/features/projects/pages/user_adds_domain_spec.rb new file mode 100644 index 00000000000..24c9edb79e5 --- /dev/null +++ b/spec/features/projects/pages/user_adds_domain_spec.rb @@ -0,0 +1,185 @@ +# frozen_string_literal: true +require 'spec_helper' + +RSpec.describe 'User adds pages domain', :js do + include LetsEncryptHelpers + + let_it_be(:project) { create(:project, pages_https_only: false) } + let(:user) { create(:user) } + + before do + allow(Gitlab.config.pages).to receive(:enabled).and_return(true) + + project.add_maintainer(user) + + sign_in(user) + end + + context 'when pages are exposed on external HTTP address', :http_pages_enabled do + let(:project) { create(:project, pages_https_only: false) } + + shared_examples 'adds new domain' do + it 'adds new domain' do + visit new_project_pages_domain_path(project) + + fill_in 'Domain', with: 'my.test.domain.com' + click_button 'Create New Domain' + + expect(page).to have_content('my.test.domain.com') + end + end + + it 'allows to add new domain' do + visit project_pages_path(project) + + expect(page).to have_content('New Domain') + end + + it_behaves_like 'adds new domain' + + context 'when project in group namespace' do + it_behaves_like 'adds new domain' do + let(:group) { create :group } + let(:project) { create(:project, namespace: group, pages_https_only: false) } + end + end + + context 'when pages domain is added' do + before do + create(:pages_domain, project: project, domain: 'my.test.domain.com') + + visit new_project_pages_domain_path(project) + end + + it 'renders certificates is disabled' do + expect(page).to have_content('Support for custom certificates is disabled') + end + + it 'does not adds new domain and renders error message' do + fill_in 'Domain', with: 'my.test.domain.com' + click_button 'Create New Domain' + + expect(page).to have_content('Domain has already been taken') + end + end + end + + context 'when pages are exposed on external HTTPS address', :https_pages_enabled, :js do + let(:certificate_pem) do + attributes_for(:pages_domain)[:certificate] + end + + let(:certificate_key) do + attributes_for(:pages_domain)[:key] + end + + it 'adds new domain with certificate' do + visit new_project_pages_domain_path(project) + + fill_in 'Domain', with: 'my.test.domain.com' + + fill_in 'Certificate (PEM)', with: certificate_pem + fill_in 'Key (PEM)', with: certificate_key + click_button 'Create New Domain' + + expect(page).to have_content('my.test.domain.com') + end + + it "adds new domain with certificate if Let's Encrypt is enabled" do + stub_lets_encrypt_settings + + visit new_project_pages_domain_path(project) + + fill_in 'Domain', with: 'my.test.domain.com' + + find('.js-auto-ssl-toggle-container .project-feature-toggle').click + + fill_in 'Certificate (PEM)', with: certificate_pem + fill_in 'Key (PEM)', with: certificate_key + click_button 'Create New Domain' + + expect(page).to have_content('my.test.domain.com') + end + + it 'shows validation error if domain is duplicated' do + project.pages_domains.create!(domain: 'my.test.domain.com') + + visit new_project_pages_domain_path(project) + + fill_in 'Domain', with: 'my.test.domain.com' + click_button 'Create New Domain' + + expect(page).to have_content('Domain has already been taken') + end + + describe 'with dns verification enabled' do + before do + stub_application_setting(pages_domain_verification_enabled: true) + end + + it 'shows the DNS verification record' do + domain = create(:pages_domain, project: project) + + visit project_pages_path(project) + + within('#content-body') { click_link 'Edit' } + expect(page).to have_field :domain_verification, with: "#{domain.verification_domain} TXT #{domain.keyed_verification_code}" + end + end + + describe 'updating the certificate for an existing domain' do + let!(:domain) do + create(:pages_domain, project: project, auto_ssl_enabled: false) + end + + it 'allows the certificate to be updated' do + visit project_pages_path(project) + + within('#content-body') { click_link 'Edit' } + click_button 'Save Changes' + + expect(page).to have_content('Domain was updated') + end + + context 'when the certificate is invalid' do + let!(:domain) do + create(:pages_domain, :without_certificate, :without_key, project: project) + end + + it 'tells the user what the problem is' do + visit project_pages_path(project) + + within('#content-body') { click_link 'Edit' } + + fill_in 'Certificate (PEM)', with: 'invalid data' + click_button 'Save Changes' + + expect(page).to have_content('Certificate must be a valid PEM certificate') + expect(page).to have_content('Certificate misses intermediates') + expect(page).to have_content("Key doesn't match the certificate") + end + end + + it 'allows the certificate to be removed', :js do + visit project_pages_path(project) + + within('#content-body') { click_link 'Edit' } + + accept_confirm { click_link 'Remove' } + + expect(page).to have_field('Certificate (PEM)', with: '') + expect(page).to have_field('Key (PEM)', with: '') + domain.reload + expect(domain.certificate).to be_nil + expect(domain.key).to be_nil + end + + it 'shows the DNS CNAME record' do + visit project_pages_path(project) + + within('#content-body') { click_link 'Edit' } + expect(page).to have_field :domain_dns, with: "#{domain.domain} CNAME #{domain.project.pages_subdomain}.#{Settings.pages.host}." + end + end + end +end diff --git a/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb new file mode 100644 index 00000000000..cf8438d5e6f --- /dev/null +++ b/spec/features/projects/pages/user_edits_lets_encrypt_settings_spec.rb @@ -0,0 +1,167 @@ +# frozen_string_literal: true +require 'spec_helper' + +RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled do + include LetsEncryptHelpers + + let(:project) { create(:project, pages_https_only: false) } + let(:user) { create(:user) } + let(:role) { :maintainer } + let(:certificate_pem) { attributes_for(:pages_domain)[:certificate] } + + let(:certificate_key) { attributes_for(:pages_domain)[:key] } + + before do + allow(Gitlab.config.pages).to receive(:enabled).and_return(true) + stub_lets_encrypt_settings + + project.add_role(user, role) + sign_in(user) + project.namespace.update!(owner: user) + allow_next_instance_of(Project) do |instance| + allow(instance).to receive(:pages_deployed?) { true } + end + end + + it "creates new domain with Let's Encrypt enabled by default" do + visit new_project_pages_domain_path(project) + + fill_in 'Domain', with: 'my.test.domain.com' + + expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true' + click_button 'Create New Domain' + + expect(page).to have_content('my.test.domain.com') + expect(PagesDomain.find_by_domain('my.test.domain.com').auto_ssl_enabled).to eq(true) + end + + context 'when the auto SSL management is initially disabled' do + let(:domain) do + create(:pages_domain, auto_ssl_enabled: false, project: project) + end + + it 'enables auto SSL and dynamically updates the form accordingly', :js do + visit project_pages_domain_path(project, domain) + + expect(domain.auto_ssl_enabled).to eq false + + expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false' + expect(page).to have_selector '.card-header', text: 'Certificate' + expect(page).to have_text domain.subject + + find('.js-auto-ssl-toggle-container .project-feature-toggle').click + + expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true' + expect(page).not_to have_selector '.card-header', text: 'Certificate' + expect(page).not_to have_text domain.subject + + click_on 'Save Changes' + + expect(domain.reload.auto_ssl_enabled).to eq true + end + end + + context 'when the auto SSL management is initially enabled' do + let(:domain) do + create(:pages_domain, :letsencrypt, auto_ssl_enabled: true, project: project) + end + + it 'disables auto SSL and dynamically updates the form accordingly', :js do + visit project_pages_domain_path(project, domain) + + expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true' + expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea' + expect(page).not_to have_field 'Key (PEM)', type: 'textarea' + + find('.js-auto-ssl-toggle-container .project-feature-toggle').click + + expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false' + expect(page).to have_field 'Certificate (PEM)', type: 'textarea' + expect(page).to have_field 'Key (PEM)', type: 'textarea' + + click_on 'Save Changes' + + expect(domain.reload.auto_ssl_enabled).to eq false + end + end + + context "when we failed to obtain Let's Encrypt certificate", :js do + let(:domain) do + create(:pages_domain, auto_ssl_enabled: true, auto_ssl_failed: true, project: project) + end + + it 'user can retry obtaining certificate' do + visit project_pages_domain_path(project, domain) + + expect(page).to have_text("Something went wrong while obtaining the Let's Encrypt certificate.") + + click_on('Retry') + + expect(page).to have_text("GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later.") + end + end + + shared_examples 'user sees private keys only for user provided certificate' do + shared_examples 'user do not see private key' do + it 'user do not see private key' do + visit project_pages_domain_path(project, domain) + + expect(page).not_to have_selector '.card-header', text: 'Certificate' + expect(page).not_to have_text domain.subject + end + end + + context 'when auto_ssl is enabled for domain' do + let(:domain) { create(:pages_domain, :letsencrypt, project: project, auto_ssl_enabled: true) } + + include_examples 'user do not see private key' + end + + context 'when auto_ssl is disabled for domain' do + let(:domain) { create(:pages_domain, :letsencrypt, project: project) } + + include_examples 'user do not see private key' + end + + context 'when certificate is provided by user' do + let(:domain) { create(:pages_domain, project: project, auto_ssl_enabled: false) } + + it 'user sees certificate subject' do + visit project_pages_domain_path(project, domain) + + expect(page).to have_selector '.card-header', text: 'Certificate' + expect(page).to have_text domain.subject + end + + it 'user can delete the certificate', :js do + visit project_pages_domain_path(project, domain) + + expect(page).to have_selector '.card-header', text: 'Certificate' + expect(page).to have_text domain.subject + within('.card') { accept_confirm { click_on 'Remove' } } + expect(page).to have_field 'Certificate (PEM)', with: '' + expect(page).to have_field 'Key (PEM)', with: '' + end + end + end + + include_examples 'user sees private keys only for user provided certificate' + + context 'when letsencrypt is disabled' do + let(:domain) do + create(:pages_domain, auto_ssl_enabled: false, project: project) + end + + before do + stub_application_setting(lets_encrypt_terms_of_service_accepted: false) + + visit project_pages_domain_path(project, domain) + end + + it "does not render the Let's Encrypt field", :js do + expect(page).not_to have_selector '.js-auto-ssl-toggle-container' + end + + include_examples 'user sees private keys only for user provided certificate' + end +end diff --git a/spec/features/projects/pages/user_edits_settings_spec.rb b/spec/features/projects/pages/user_edits_settings_spec.rb new file mode 100644 index 00000000000..3649fae17ce --- /dev/null +++ b/spec/features/projects/pages/user_edits_settings_spec.rb @@ -0,0 +1,201 @@ +# frozen_string_literal: true +require 'spec_helper' + +RSpec.describe 'Pages edits pages settings', :js do + let(:project) { create(:project, pages_https_only: false) } + let(:user) { create(:user) } + + before do + allow(Gitlab.config.pages).to receive(:enabled).and_return(true) + + project.add_maintainer(user) + + sign_in(user) + end + + context 'when user is the owner' do + before do + project.namespace.update!(owner: user) + end + + context 'when pages deployed' do + before do + project.mark_pages_as_deployed + end + + it 'renders Access pages' do + visit project_pages_path(project) + + expect(page).to have_content('Access pages') + end + + context 'when pages are disabled in the project settings' do + it 'renders disabled warning' do + project.project_feature.update!(pages_access_level: ProjectFeature::DISABLED) + + visit project_pages_path(project) + + expect(page).to have_content('GitLab Pages are disabled for this project') + end + end + + it 'renders first deployment warning' do + visit project_pages_path(project) + + expect(page).to have_content('It may take up to 30 minutes before the site is available after the first deployment.') + end + + shared_examples 'does not render access control warning' do + it 'does not render access control warning' do + visit project_pages_path(project) + + expect(page).not_to have_content('Access Control is enabled for this Pages website') + end + end + + include_examples 'does not render access control warning' + + context 'when access control is enabled in gitlab settings' do + before do + stub_pages_setting(access_control: true) + end + + it 'renders access control warning' do + visit project_pages_path(project) + + expect(page).to have_content('Access Control is enabled for this Pages website') + end + + context 'when pages are public' do + before do + project.project_feature.update!(pages_access_level: ProjectFeature::PUBLIC) + end + + include_examples 'does not render access control warning' + end + end + + context 'when support for external domains is disabled' do + it 'renders message that support is disabled' do + visit project_pages_path(project) + + expect(page).to have_content('Support for domains and certificates is disabled') + end + end + end + + it 'does not see anything to destroy' do + visit project_pages_path(project) + + expect(page).to have_content('Configure pages') + expect(page).not_to have_link('Remove pages') + end + + describe 'project settings page' do + it 'renders "Pages" tab' do + visit edit_project_path(project) + + page.within '.nav-sidebar' do + expect(page).to have_link('Pages') + end + end + + context 'when pages are disabled' do + before do + allow(Gitlab.config.pages).to receive(:enabled).and_return(false) + end + + it 'does not render "Pages" tab' do + visit edit_project_path(project) + + page.within '.nav-sidebar' do + expect(page).not_to have_link('Pages') + end + end + end + end + end + + describe 'HTTPS settings', :https_pages_enabled do + before do + project.namespace.update!(owner: user) + + project.mark_pages_as_deployed + end + + it 'tries to change the setting' do + visit project_pages_path(project) + expect(page).to have_content("Force HTTPS (requires valid certificates)") + + uncheck :project_pages_https_only + + click_button 'Save' + + expect(page).to have_text('Your changes have been saved') + expect(page).not_to have_checked_field('project_pages_https_only') + end + + context 'setting could not be updated' do + let(:service) { instance_double('Projects::UpdateService') } + + before do + allow(Projects::UpdateService).to receive(:new).and_return(service) + allow(service).to receive(:execute).and_return(status: :error, message: 'Some error has occured') + end + + it 'tries to change the setting' do + visit project_pages_path(project) + + uncheck :project_pages_https_only + + click_button 'Save' + + expect(page).to have_text('Some error has occured') + end + end + + context 'non-HTTPS domain exists' do + let(:project) { create(:project, pages_https_only: false) } + + before do + create(:pages_domain, :without_key, :without_certificate, project: project) + end + + it 'the setting is disabled' do + visit project_pages_path(project) + + expect(page).to have_field(:project_pages_https_only, disabled: true) + expect(page).to have_button('Save') + end + end + + context 'HTTPS pages are disabled', :https_pages_disabled do + it 'the setting is unavailable' do + visit project_pages_path(project) + + expect(page).not_to have_field(:project_pages_https_only) + expect(page).not_to have_content('Force HTTPS (requires valid certificates)') + expect(page).to have_button('Save') + end + end + end + + describe 'Remove page' do + context 'when pages are deployed' do + before do + project.mark_pages_as_deployed + end + + it 'removes the pages', :sidekiq_inline do + visit project_pages_path(project) + + expect(page).to have_link('Remove pages') + + accept_confirm { click_link 'Remove pages' } + + expect(page).to have_content('Pages were scheduled for removal') + expect(project.reload.pages_deployed?).to be_falsey + end + end + end +end -- cgit v1.2.1