From d550211eb101d82da2887e1eccde5c338388669d Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Mon, 7 May 2018 23:39:37 +0000 Subject: [PATCH] Replace the `project/builds/artifacts.feature` spinach test with an rspec analog --- ...inach-project-builds-artifacts-feature.yml | 5 + features/project/builds/artifacts.feature | 65 ----------- features/steps/project/builds/artifacts.rb | 98 ---------------- features/steps/shared/builds.rb | 53 --------- .../projects/artifacts/browse_spec.rb | 67 ----------- .../projects/artifacts/download_spec.rb | 61 ---------- .../artifacts/user_browses_artifacts_spec.rb | 110 ++++++++++++++++++ .../user_downloads_artifacts_spec.rb | 44 +++++++ 8 files changed, 159 insertions(+), 344 deletions(-) create mode 100644 changelogs/unreleased/blackst0ne-replace-spinach-project-builds-artifacts-feature.yml delete mode 100644 features/project/builds/artifacts.feature delete mode 100644 features/steps/project/builds/artifacts.rb delete mode 100644 features/steps/shared/builds.rb delete mode 100644 spec/features/projects/artifacts/browse_spec.rb delete mode 100644 spec/features/projects/artifacts/download_spec.rb create mode 100644 spec/features/projects/artifacts/user_browses_artifacts_spec.rb create mode 100644 spec/features/projects/artifacts/user_downloads_artifacts_spec.rb diff --git a/changelogs/unreleased/blackst0ne-replace-spinach-project-builds-artifacts-feature.yml b/changelogs/unreleased/blackst0ne-replace-spinach-project-builds-artifacts-feature.yml new file mode 100644 index 00000000000..98c56cf2b57 --- /dev/null +++ b/changelogs/unreleased/blackst0ne-replace-spinach-project-builds-artifacts-feature.yml @@ -0,0 +1,5 @@ +--- +title: 'Replace the `project/builds/artifacts.feature` spinach test with an rspec analog' +merge_request: 18729 +author: '@blackst0ne' +type: other diff --git a/features/project/builds/artifacts.feature b/features/project/builds/artifacts.feature deleted file mode 100644 index 5abc24949cf..00000000000 --- a/features/project/builds/artifacts.feature +++ /dev/null @@ -1,65 +0,0 @@ -Feature: Project Builds Artifacts - Background: - Given I sign in as a user - And I own a project - And project has CI enabled - And project has a recent build - - Scenario: I download build artifacts - Given recent build has artifacts available - When I visit recent build details page - And I click artifacts download button - Then download of build artifacts archive starts - - Scenario: I browse build artifacts - Given recent build has artifacts available - And recent build has artifacts metadata available - When I visit recent build details page - And I click artifacts browse button - Then I should see content of artifacts archive - And I should see the build header - - Scenario: I browse subdirectory of build artifacts - Given recent build has artifacts available - And recent build has artifacts metadata available - When I visit recent build details page - And I click artifacts browse button - And I click link to subdirectory within build artifacts - Then I should see content of subdirectory within artifacts archive - And I should see the directory name in the breadcrumb - - Scenario: I browse directory with UTF-8 characters in name - Given recent build has artifacts available - And recent build has artifacts metadata available - And recent build artifacts contain directory with UTF-8 characters - When I visit recent build details page - And I click artifacts browse button - And I navigate to directory with UTF-8 characters in name - Then I should see content of directory with UTF-8 characters in name - - Scenario: I try to browse directory with invalid UTF-8 characters in name - Given recent build has artifacts available - And recent build has artifacts metadata available - And recent build artifacts contain directory with invalid UTF-8 characters - When I visit recent build details page - And I click artifacts browse button - And I navigate to parent directory of directory with invalid name - Then I should not see directory with invalid name on the list - - @javascript - Scenario: I download a single file from build artifacts - Given recent build has artifacts available - And recent build has artifacts metadata available - When I visit recent build details page - And I click artifacts browse button - And I click a link to file within build artifacts - Then I see a download link - - @javascript - Scenario: I click on a row in an artifacts table - Given recent build has artifacts available - And recent build has artifacts metadata available - When I visit recent build details page - And I click artifacts browse button - And I click a first row within build artifacts table - Then page with a coresponding path is loading diff --git a/features/steps/project/builds/artifacts.rb b/features/steps/project/builds/artifacts.rb deleted file mode 100644 index 4b72355b125..00000000000 --- a/features/steps/project/builds/artifacts.rb +++ /dev/null @@ -1,98 +0,0 @@ -class Spinach::Features::ProjectBuildsArtifacts < Spinach::FeatureSteps - include SharedAuthentication - include SharedProject - include SharedBuilds - include RepoHelpers - include WaitForRequests - - step 'I click artifacts download button' do - click_link 'Download' - end - - step 'I click artifacts browse button' do - click_link 'Browse' - expect(page).not_to have_selector('.build-sidebar') - end - - step 'I should see content of artifacts archive' do - page.within('.tree-table') do - expect(page).to have_no_content '..' - expect(page).to have_content 'other_artifacts_0.1.2' - expect(page).to have_content 'ci_artifacts.txt' - expect(page).to have_content 'rails_sample.jpg' - end - end - - step 'I should see the build header' do - page.within('.build-header') do - expect(page).to have_content "Job ##{@build.id} in pipeline ##{@pipeline.id} for #{@pipeline.short_sha}" - end - end - - step 'I click link to subdirectory within build artifacts' do - page.within('.tree-table') { click_link 'other_artifacts_0.1.2' } - end - - step 'I should see content of subdirectory within artifacts archive' do - page.within('.tree-table') do - expect(page).to have_content '..' - expect(page).to have_content 'another-subdirectory' - expect(page).to have_content 'doc_sample.txt' - end - end - - step 'I should see the directory name in the breadcrumb' do - page.within('.repo-breadcrumb') do - expect(page).to have_content 'other_artifacts_0.1.2' - end - end - - step 'recent build artifacts contain directory with UTF-8 characters' do - # metadata fixture contains relevant directory - end - - step 'I navigate to directory with UTF-8 characters in name' do - page.within('.tree-table') { click_link 'tests_encoding' } - page.within('.tree-table') { click_link 'utf8 test dir ✓' } - end - - step 'I should see content of directory with UTF-8 characters in name' do - page.within('.tree-table') do - expect(page).to have_content '..' - expect(page).to have_content 'regular_file_2' - end - end - - step 'recent build artifacts contain directory with invalid UTF-8 characters' do - # metadata fixture contains relevant directory - end - - step 'I navigate to parent directory of directory with invalid name' do - page.within('.tree-table') { click_link 'tests_encoding' } - end - - step 'I should not see directory with invalid name on the list' do - page.within('.tree-table') do - expect(page).to have_no_content('non-utf8-dir') - end - end - - step 'I click a link to file within build artifacts' do - page.within('.tree-table') { find_link('ci_artifacts.txt').click } - wait_for_requests - end - - step 'I see a download link' do - expect(page).to have_link 'download it' - end - - step 'I click a first row within build artifacts table' do - row = first('tr[data-link]') - @row_path = row['data-link'] - row.click - end - - step 'page with a coresponding path is loading' do - expect(current_path).to eq @row_path - end -end diff --git a/features/steps/shared/builds.rb b/features/steps/shared/builds.rb deleted file mode 100644 index c2197584d8d..00000000000 --- a/features/steps/shared/builds.rb +++ /dev/null @@ -1,53 +0,0 @@ -module SharedBuilds - include Spinach::DSL - - step 'project has CI enabled' do - @project.enable_ci - end - - step 'project has coverage enabled' do - @project.update_attribute(:build_coverage_regex, /Coverage (\d+)%/) - end - - step 'project has a recent build' do - @pipeline = create(:ci_empty_pipeline, project: @project, sha: @project.commit.sha, ref: 'master') - @build = create(:ci_build, :running, :coverage, :trace_artifact, pipeline: @pipeline) - end - - step 'recent build is successful' do - @build.success - end - - step 'recent build failed' do - @build.drop - end - - step 'project has another build that is running' do - create(:ci_build, pipeline: @pipeline, name: 'second build', status_event: 'run') - end - - step 'I visit recent build details page' do - visit project_job_path(@project, @build) - end - - step 'recent build has artifacts available' do - artifacts = Rails.root + 'spec/fixtures/ci_build_artifacts.zip' - archive = fixture_file_upload(artifacts, 'application/zip') - @build.update_attributes(legacy_artifacts_file: archive) - end - - step 'recent build has artifacts metadata available' do - metadata = Rails.root + 'spec/fixtures/ci_build_artifacts_metadata.gz' - gzip = fixture_file_upload(metadata, 'application/x-gzip') - @build.update_attributes(legacy_artifacts_metadata: gzip) - end - - step 'recent build has a build trace' do - @build.trace.set('job trace') - end - - step 'download of build artifacts archive starts' do - expect(page.response_headers['Content-Type']).to eq 'application/zip' - expect(page.response_headers['Content-Transfer-Encoding']).to eq 'binary' - end -end diff --git a/spec/features/projects/artifacts/browse_spec.rb b/spec/features/projects/artifacts/browse_spec.rb deleted file mode 100644 index cb69aff8d5f..00000000000 --- a/spec/features/projects/artifacts/browse_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -require 'spec_helper' - -feature 'Browse artifact', :js do - let(:project) { create(:project, :public) } - let(:pipeline) { create(:ci_empty_pipeline, project: project) } - let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) } - let(:browse_url) do - browse_path('other_artifacts_0.1.2') - end - - def browse_path(path) - browse_project_job_artifacts_path(project, job, path) - end - - context 'when visiting old URL' do - before do - visit browse_url.sub('/-/jobs', '/builds') - end - - it "redirects to new URL" do - expect(page.current_path).to eq(browse_url) - end - end - - context 'when browsing a directory with an text file' do - let(:txt_entry) { job.artifacts_metadata_entry('other_artifacts_0.1.2/doc_sample.txt') } - - before do - allow(Gitlab.config.pages).to receive(:enabled).and_return(true) - allow(Gitlab.config.pages).to receive(:artifacts_server).and_return(true) - end - - context 'when the project is public' do - it "shows external link icon and styles" do - visit browse_url - - link = first('.tree-item-file-external-link') - - expect(page).to have_link('doc_sample.txt', href: file_project_job_artifacts_path(project, job, path: txt_entry.blob.path)) - expect(link[:target]).to eq('_blank') - expect(link[:rel]).to include('noopener') - expect(link[:rel]).to include('noreferrer') - expect(page).to have_selector('.js-artifact-tree-external-icon') - end - end - - context 'when the project is private' do - let!(:private_project) { create(:project, :private) } - let(:pipeline) { create(:ci_empty_pipeline, project: private_project) } - let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) } - let(:user) { create(:user) } - - before do - private_project.add_developer(user) - - sign_in(user) - end - - it 'shows internal link styles' do - visit browse_project_job_artifacts_path(private_project, job, 'other_artifacts_0.1.2') - - expect(page).to have_link('doc_sample.txt') - expect(page).not_to have_selector('.js-artifact-tree-external-icon') - end - end - end -end diff --git a/spec/features/projects/artifacts/download_spec.rb b/spec/features/projects/artifacts/download_spec.rb deleted file mode 100644 index 6f76c14910b..00000000000 --- a/spec/features/projects/artifacts/download_spec.rb +++ /dev/null @@ -1,61 +0,0 @@ -require 'spec_helper' - -feature 'Download artifact' do - let(:project) { create(:project, :public) } - let(:pipeline) { create(:ci_empty_pipeline, status: :success, project: project) } - let(:job) { create(:ci_build, :artifacts, :success, pipeline: pipeline) } - - shared_examples 'downloading' do - it 'downloads the zip' do - expect(page.response_headers['Content-Disposition']) - .to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"}) - - # Check the content does match, but don't print this as error message - expect(page.source.b == job.artifacts_file.file.read.b) - end - end - - context 'when downloading' do - before do - visit download_url - end - - context 'via job id' do - let(:download_url) do - download_project_job_artifacts_path(project, job) - end - - it_behaves_like 'downloading' - end - - context 'via branch name and job name' do - let(:download_url) do - latest_succeeded_project_artifacts_path(project, "#{pipeline.ref}/download", job: job.name) - end - - it_behaves_like 'downloading' - end - end - - context 'when visiting old URL' do - before do - visit download_url.sub('/-/jobs', '/builds') - end - - context 'via job id' do - let(:download_url) do - download_project_job_artifacts_path(project, job) - end - - it_behaves_like 'downloading' - end - - context 'via branch name and job name' do - let(:download_url) do - latest_succeeded_project_artifacts_path(project, "#{pipeline.ref}/download", job: job.name) - end - - it_behaves_like 'downloading' - end - end -end diff --git a/spec/features/projects/artifacts/user_browses_artifacts_spec.rb b/spec/features/projects/artifacts/user_browses_artifacts_spec.rb new file mode 100644 index 00000000000..9ebbbaea911 --- /dev/null +++ b/spec/features/projects/artifacts/user_browses_artifacts_spec.rb @@ -0,0 +1,110 @@ +require "spec_helper" + +describe "User browses artifacts" do + let(:project) { create(:project, :public) } + let(:pipeline) { create(:ci_empty_pipeline, project: project) } + let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) } + let(:browse_url) { browse_project_job_artifacts_path(project, job, "other_artifacts_0.1.2") } + + context "when visiting old URL" do + it "redirects to new URL" do + visit(browse_url.sub("/-/jobs", "/builds")) + + expect(page.current_path).to eq(browse_url) + end + end + + context "when browsing artifacts root directory" do + before do + visit(browse_project_job_artifacts_path(project, job)) + end + + it "shows artifacts" do + expect(page).not_to have_selector(".build-sidebar") + + page.within(".tree-table") do + expect(page).to have_no_content("..") + .and have_content("other_artifacts_0.1.2") + .and have_content("ci_artifacts.txt") + .and have_content("rails_sample.jpg") + end + + page.within(".build-header") do + expect(page).to have_content("Job ##{job.id} in pipeline ##{pipeline.id} for #{pipeline.short_sha}") + end + end + + it "shows an artifact" do + click_link("ci_artifacts.txt") + + expect(page).to have_link("download it") + end + end + + context "when browsing a directory with UTF-8 characters in its name" do + before do + visit(browse_project_job_artifacts_path(project, job)) + end + + it "shows correct content", :js do + page.within(".tree-table") do + click_link("tests_encoding") + + expect(page).to have_no_content("non-utf8-dir") + + click_link("utf8 test dir ✓") + + expect(page).to have_content("..").and have_content("regular_file_2") + end + end + end + + context "when browsing a directory with a text file" do + let(:txt_entry) { job.artifacts_metadata_entry("other_artifacts_0.1.2/doc_sample.txt") } + + before do + allow(Gitlab.config.pages).to receive(:enabled).and_return(true) + allow(Gitlab.config.pages).to receive(:artifacts_server).and_return(true) + end + + context "when the project is public" do + before do + visit(browse_url) + end + + it "shows correct content" do + link = first(".tree-item-file-external-link") + + expect(link[:target]).to eq("_blank") + expect(link[:rel]).to include("noopener").and include("noreferrer") + expect(page).to have_link("doc_sample.txt", href: file_project_job_artifacts_path(project, job, path: txt_entry.blob.path)) + .and have_selector(".js-artifact-tree-external-icon") + + page.within(".tree-table") do + expect(page).to have_content("..").and have_content("another-subdirectory") + end + + page.within(".repo-breadcrumb") do + expect(page).to have_content("other_artifacts_0.1.2") + end + end + end + + context "when the project is private" do + let!(:private_project) { create(:project, :private) } + let(:pipeline) { create(:ci_empty_pipeline, project: private_project) } + let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) } + let(:user) { create(:user) } + + before do + private_project.add_developer(user) + + sign_in(user) + + visit(browse_project_job_artifacts_path(private_project, job, "other_artifacts_0.1.2")) + end + + it { expect(page).to have_link("doc_sample.txt").and have_no_selector(".js-artifact-tree-external-icon") } + end + end +end diff --git a/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb new file mode 100644 index 00000000000..67ed2f18d76 --- /dev/null +++ b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb @@ -0,0 +1,44 @@ +require "spec_helper" + +describe "User downloads artifacts" do + set(:project) { create(:project, :public) } + set(:pipeline) { create(:ci_empty_pipeline, status: :success, project: project) } + set(:job) { create(:ci_build, :artifacts, :success, pipeline: pipeline) } + + shared_examples "downloading" do + it "downloads the zip" do + expect(page.response_headers["Content-Disposition"]).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"}) + expect(page.response_headers['Content-Transfer-Encoding']).to eq("binary") + expect(page.response_headers['Content-Type']).to eq("application/zip") + expect(page.source.b).to eq(job.artifacts_file.file.read.b) + end + end + + context "when downloading" do + before do + visit(url) + end + + context "via job id" do + set(:url) { download_project_job_artifacts_path(project, job) } + + it_behaves_like "downloading" + end + + context "via branch name and job name" do + set(:url) { latest_succeeded_project_artifacts_path(project, "#{pipeline.ref}/download", job: job.name) } + + it_behaves_like "downloading" + end + + context "via clicking the `Download` button" do + set(:url) { project_job_path(project, job) } + + before do + click_link("Download") + end + + it_behaves_like "downloading" + end + end +end