Commit 2fd86671 authored by Mark Lapierre's avatar Mark Lapierre

Merge branch '353393-blob-refactor-disabled-coverage' into 'master'

Ensure we have sufficient test coverage for viewing blobs

See merge request gitlab-org/gitlab!81510
parents 50cec3d8 eb83eeb6
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Path Locks', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :repository, namespace: user.namespace) }
let(:tree_path) { project_tree_path(project, project.repository.root_ref) }
before do
allow(project).to receive(:feature_available?).with(:file_locks) { true }
stub_feature_flags(bootstrap_confirmation_modals: false)
stub_feature_flags(refactor_blob_viewer: false)
project.add_maintainer(user)
sign_in(user)
visit tree_path
wait_for_requests
end
it 'locking folders' do
within '.tree-content-holder' do
click_link "encoding"
end
find('.js-path-lock').click
wait_for_requests
page.within '.modal' do
expect(page).to have_selector('.modal-body', visible: true)
expect(page).to have_css('.modal-body', text: 'Are you sure you want to lock this directory?')
click_button "OK"
end
expect(page).to have_link('Unlock')
end
it 'locking files' do
page_tree = find('.tree-content-holder')
within page_tree do
click_link "VERSION"
end
within '.file-actions' do
click_link "Lock"
end
page.within '.modal' do
expect(page).to have_css('.modal-body', text: 'Are you sure you want to lock VERSION?')
click_button "OK"
end
expect(page).to have_link('Unlock')
end
it 'unlocking files' do
page_tree = find('.tree-content-holder')
within page_tree do
click_link "VERSION"
end
within '.file-actions' do
click_link "Lock"
end
page.within '.modal' do
expect(page).to have_css('.modal-body', text: 'Are you sure you want to lock VERSION?')
click_button "OK"
end
expect(page).to have_link('Lock')
end
it 'managing of lock list' do
create :path_lock, path: 'encoding', user: user, project: project
click_link "Locked Files"
within '.locks' do
expect(page).to have_content('encoding')
accept_confirm(text: 'Are you sure you want to unlock encoding?') { click_link "Unlock" }
expect(page).not_to have_content('encoding')
end
end
end
...@@ -1033,71 +1033,6 @@ RSpec.describe 'File blob', :js do ...@@ -1033,71 +1033,6 @@ RSpec.describe 'File blob', :js do
stub_feature_flags(refactor_blob_viewer: false) stub_feature_flags(refactor_blob_viewer: false)
end end
context 'when ref switch' do
# We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
# This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351558
def switch_ref_to(ref_name)
first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
page.within '.project-refs-form' do
click_link ref_name
wait_for_requests
end
end
context 'when highlighting lines' do
it 'displays single highlighted line number of different ref' do
visit_blob('files/js/application.js', anchor: 'L1')
switch_ref_to('feature')
page.within '.blob-content' do
expect(find_by_id('LC1')[:class]).to include("hll")
end
end
it 'displays multiple highlighted line numbers of different ref' do
visit_blob('files/js/application.js', anchor: 'L1-3')
switch_ref_to('feature')
page.within '.blob-content' do
expect(find_by_id('LC1')[:class]).to include("hll")
expect(find_by_id('LC2')[:class]).to include("hll")
expect(find_by_id('LC3')[:class]).to include("hll")
end
end
end
end
context 'visiting with a line number anchor' do
# We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
# This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351558
before do
visit_blob('files/markdown/ruby-style-guide.md', anchor: 'L1')
end
it 'displays the blob using the simple viewer' do
aggregate_failures do
# hides the rich viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]')
expect(page).not_to have_selector('.blob-viewer[data-type="rich"]')
# highlights the line in question
expect(page).to have_selector('#LC1.hll')
# shows highlighted Markdown code
expect(page).to have_css(".js-syntax-highlight")
expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
# shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
end
end
end
context 'binary file that appears to be text in the first 1024 bytes' do context 'binary file that appears to be text in the first 1024 bytes' do
# We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled # We need to unsre that this test runs with the refactor_blob_viewer feature flag enabled
# This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351559 # This will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/351559
...@@ -1158,503 +1093,5 @@ RSpec.describe 'File blob', :js do ...@@ -1158,503 +1093,5 @@ RSpec.describe 'File blob', :js do
end end
end end
end end
context 'files with auxiliary viewers' do
# This context is the same as the other 'files with auxiliary viewers' in this file, we just ensure that the auxiliary viewers still work this the refactor_blob_viewer disabled
# It should be safe to remove once we rollout the refactored blob viewer
describe '.gitlab-ci.yml' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add .gitlab-ci.yml",
file_path: '.gitlab-ci.yml',
file_content: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
).execute
visit_blob('.gitlab-ci.yml')
end
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that configuration is valid
expect(page).to have_content('This GitLab CI configuration is valid.')
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
describe '.gitlab/route-map.yml' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add .gitlab/route-map.yml",
file_path: '.gitlab/route-map.yml',
file_content: <<-MAP.strip_heredoc
# Team data
- source: 'data/team.yml'
public: 'team/'
MAP
).execute
visit_blob('.gitlab/route-map.yml')
end
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that map is valid
expect(page).to have_content('This Route Map is valid.')
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
describe '.gitlab/dashboards/custom-dashboard.yml' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add .gitlab/dashboards/custom-dashboard.yml",
file_path: '.gitlab/dashboards/custom-dashboard.yml',
file_content: file_content
).execute
end
context 'with metrics_dashboard_exhaustive_validations feature flag off' do
before do
stub_feature_flags(metrics_dashboard_exhaustive_validations: false)
visit_blob('.gitlab/dashboards/custom-dashboard.yml')
end
context 'valid dashboard file' do
let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that dashboard yaml is valid
expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
context 'invalid dashboard file' do
let(:file_content) { "dashboard: 'invalid'" }
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that dashboard yaml is invalid
expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
expect(page).to have_content("panel_groups: should be an array of panel_groups objects")
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
end
context 'with metrics_dashboard_exhaustive_validations feature flag on' do
before do
stub_feature_flags(metrics_dashboard_exhaustive_validations: true)
visit_blob('.gitlab/dashboards/custom-dashboard.yml')
end
context 'valid dashboard file' do
let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that dashboard yaml is valid
expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
context 'invalid dashboard file' do
let(:file_content) { "dashboard: 'invalid'" }
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that dashboard yaml is invalid
expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
expect(page).to have_content("root is missing required keys: panel_groups")
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
end
end
context 'LICENSE' do
before do
visit_blob('LICENSE')
end
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows license
expect(page).to have_content('This project is licensed under the MIT License.')
# shows a learn more link
expect(page).to have_link('Learn more', href: 'http://choosealicense.com/licenses/mit/')
end
end
end
context '*.gemspec' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add activerecord.gemspec",
file_path: 'activerecord.gemspec',
file_content: <<-SPEC.strip_heredoc
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "activerecord"
end
SPEC
).execute
visit_blob('activerecord.gemspec')
end
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows names of dependency manager and package
expect(page).to have_content('This project manages its dependencies using RubyGems.')
# shows a learn more link
expect(page).to have_link('Learn more', href: 'https://rubygems.org/')
end
end
end
context 'CONTRIBUTING.md' do
before do
file_name = 'CONTRIBUTING.md'
create_file(file_name, '## Contribution guidelines')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("After you've reviewed these contribution guidelines, you'll be all set to contribute to this project.")
end
end
end
context 'CHANGELOG.md' do
before do
file_name = 'CHANGELOG.md'
create_file(file_name, '## Changelog for v1.0.0')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("To find the state of this project's repository at the time of any of these versions, check out the tags.")
end
end
end
context 'Cargo.toml' do
before do
file_name = 'Cargo.toml'
create_file(file_name, '
[package]
name = "hello_world" # the name of the package
version = "0.1.0" # the current version, obeying semver
authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Cargo.")
end
end
end
context 'Cartfile' do
before do
file_name = 'Cartfile'
create_file(file_name, '
gitlab "Alamofire/Alamofire" == 4.9.0
gitlab "Alamofire/AlamofireImage" ~> 3.4
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Carthage.")
end
end
end
context 'composer.json' do
before do
file_name = 'composer.json'
create_file(file_name, '
{
"license": "MIT"
}
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Composer.")
end
end
end
context 'Gemfile' do
before do
file_name = 'Gemfile'
create_file(file_name, '
source "https://rubygems.org"
# Gems here
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Bundler.")
end
end
end
context 'Godeps.json' do
before do
file_name = 'Godeps.json'
create_file(file_name, '
{
"GoVersion": "go1.6"
}
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using godep.")
end
end
end
context 'go.mod' do
before do
file_name = 'go.mod'
create_file(file_name, '
module example.com/mymodule
go 1.14
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Go Modules.")
end
end
end
context 'package.json' do
before do
file_name = 'package.json'
create_file(file_name, '
{
"name": "my-awesome-package",
"version": "1.0.0"
}
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using npm.")
end
end
end
context 'podfile' do
before do
file_name = 'podfile'
create_file(file_name, 'platform :ios, "8.0"')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using CocoaPods.")
end
end
end
context 'test.podspec' do
before do
file_name = 'test.podspec'
create_file(file_name, '
Pod::Spec.new do |s|
s.name = "TensorFlowLiteC"
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using CocoaPods.")
end
end
end
context 'JSON.podspec.json' do
before do
file_name = 'JSON.podspec.json'
create_file(file_name, '
{
"name": "JSON"
}
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using CocoaPods.")
end
end
end
context 'requirements.txt' do
before do
file_name = 'requirements.txt'
create_file(file_name, 'Project requirements')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using pip.")
end
end
end
context 'yarn.lock' do
before do
file_name = 'yarn.lock'
create_file(file_name, '
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Yarn.")
end
end
end
context 'openapi.yml' do
before do
file_name = 'openapi.yml'
create_file(file_name, '
swagger: \'2.0\'
info:
title: Classic API Resource Documentation
description: |
<div class="foo-bar" style="background-color: red;" data-foo-bar="baz">
<h1>Swagger API documentation</h1>
</div>
version: production
basePath: /JSSResource/
produces:
- application/xml
- application/json
consumes:
- application/xml
- application/json
security:
- basicAuth: []
paths:
/accounts:
get:
responses:
\'200\':
description: No response was specified
tags:
- accounts
operationId: findAccounts
summary: Finds all accounts
')
visit_blob(file_name, useUnsafeMarkdown: '1')
click_button('Display rendered file')
wait_for_requests
end
it 'removes `style`, `class`, and `data-*`` attributes from HTML' do
expect(page).to have_css('h1', text: 'Swagger API documentation')
expect(page).not_to have_css('.foo-bar')
expect(page).not_to have_css('[style="background-color: red;"]')
expect(page).not_to have_css('[data-foo-bar="baz"]')
end
end
end
end end
end end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Balsamiq file blob', :js do
let(:project) { create(:project, :public, :repository) }
before do
stub_feature_flags(refactor_blob_viewer: false)
visit project_blob_path(project, 'add-balsamiq-file/files/images/balsamiq.bmpr')
wait_for_requests
end
it 'displays Balsamiq file content' do
expect(page).to have_content("Mobile examples")
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Blob button line permalinks (BlobLinePermalinkUpdater)', :js do
include TreeHelper
let(:project) { create(:project, :public, :repository) }
let(:path) { 'CHANGELOG' }
let(:sha) { project.repository.commit.sha }
before do
stub_feature_flags(refactor_blob_viewer: false)
end
describe 'On a file(blob)' do
def get_absolute_url(path = "")
"http://#{page.server.host}:#{page.server.port}#{path}"
end
def visit_blob(fragment = nil)
visit project_blob_path(project, tree_join('master', path), anchor: fragment)
end
describe 'Click "Permalink" button' do
it 'works with no initial line number fragment hash' do
visit_blob
expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path))))
end
it 'maintains intitial fragment hash' do
fragment = "L3"
visit_blob(fragment)
expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: fragment)))
end
it 'changes fragment hash if line number clicked' do
ending_fragment = "L5"
visit_blob
find('#L3').click
find("##{ending_fragment}").click
expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: ending_fragment)))
end
it 'with initial fragment hash, changes fragment hash if line number clicked' do
fragment = "L1"
ending_fragment = "L5"
visit_blob(fragment)
find('#L3').click
find("##{ending_fragment}").click
expect(find('.js-data-file-blob-permalink-url')['href']).to eq(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: ending_fragment)))
end
end
describe 'Click "Blame" button' do
it 'works with no initial line number fragment hash' do
visit_blob
expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path))))
end
it 'maintains intitial fragment hash' do
fragment = "L3"
visit_blob(fragment)
expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: fragment)))
end
it 'changes fragment hash if line number clicked' do
ending_fragment = "L5"
visit_blob
find('#L3').click
find("##{ending_fragment}").click
expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: ending_fragment)))
end
it 'with initial fragment hash, changes fragment hash if line number clicked' do
fragment = "L1"
ending_fragment = "L5"
visit_blob(fragment)
find('#L3').click
find("##{ending_fragment}").click
expect(find('.js-blob-blame-link')['href']).to eq(get_absolute_url(project_blame_path(project, tree_join('master', path), anchor: ending_fragment)))
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'File blob', :js do
include MobileHelpers
let(:project) { create(:project, :public, :repository) }
before do
stub_feature_flags(refactor_blob_viewer: false)
end
def visit_blob(path, anchor: nil, ref: 'master', **additional_args)
visit project_blob_path(project, File.join(ref, path), anchor: anchor, **additional_args)
wait_for_requests
end
def create_file(file_name, content)
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add #{file_name}",
file_path: file_name,
file_content: <<-SPEC.strip_heredoc
#{content}
SPEC
).execute
end
context 'Ruby file' do
before do
visit_blob('files/ruby/popen.rb')
wait_for_requests
end
it 'displays the blob' do
aggregate_failures do
# shows highlighted Ruby code
expect(page).to have_css(".js-syntax-highlight")
expect(page).to have_content("require 'fileutils'")
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
# shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
# shows a raw button
expect(page).to have_link('Open raw')
end
end
it 'displays file actions on all screen sizes' do
file_actions_selector = '.file-actions'
resize_screen_sm
expect(page).to have_selector(file_actions_selector, visible: true)
resize_screen_xs
expect(page).to have_selector(file_actions_selector, visible: true)
end
end
context 'Markdown file' do
context 'visiting directly' do
before do
visit_blob('files/markdown/ruby-style-guide.md')
wait_for_requests
end
it 'displays the blob using the rich viewer' do
aggregate_failures do
# hides the simple viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
expect(page).to have_selector('.blob-viewer[data-type="rich"]')
# shows rendered Markdown
expect(page).to have_link("PEP-8")
# shows a viewer switcher
expect(page).to have_selector('.js-blob-viewer-switcher')
# shows a disabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
# shows a raw button
expect(page).to have_link('Open raw')
end
end
context 'switching to the simple viewer' do
before do
find('.js-blob-viewer-switch-btn[data-viewer=simple]').click
wait_for_requests
end
it 'displays the blob using the simple viewer' do
aggregate_failures do
# hides the rich viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]')
expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
# shows highlighted Markdown code
expect(page).to have_css(".js-syntax-highlight")
expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
# shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
end
end
context 'switching to the rich viewer again' do
before do
find('.js-blob-viewer-switch-btn[data-viewer=rich]').click
wait_for_requests
end
it 'displays the blob using the rich viewer' do
aggregate_failures do
# hides the simple viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
expect(page).to have_selector('.blob-viewer[data-type="rich"]')
# shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
end
end
end
end
end
context 'when ref switch' do
def switch_ref_to(ref_name)
first('.qa-branches-select').click # rubocop:disable QA/SelectorUsage
page.within '.project-refs-form' do
click_link ref_name
wait_for_requests
end
end
it 'displays single highlighted line number of different ref' do
visit_blob('files/js/application.js', anchor: 'L1')
switch_ref_to('feature')
page.within '.blob-content' do
expect(find_by_id('LC1')[:class]).to include("hll")
end
end
it 'displays multiple highlighted line numbers of different ref' do
visit_blob('files/js/application.js', anchor: 'L1-3')
switch_ref_to('feature')
page.within '.blob-content' do
expect(find_by_id('LC1')[:class]).to include("hll")
expect(find_by_id('LC2')[:class]).to include("hll")
expect(find_by_id('LC3')[:class]).to include("hll")
end
end
it 'displays no highlighted number of different ref' do
Files::UpdateService.new(
project,
project.first_owner,
commit_message: 'Update',
start_branch: 'feature',
branch_name: 'feature',
file_path: 'files/js/application.js',
file_content: 'new content'
).execute
project.commit('feature').diffs.diff_files.first
visit_blob('files/js/application.js', anchor: 'L3')
switch_ref_to('feature')
page.within '.blob-content' do
expect(page).not_to have_css('.hll')
end
end
context 'successfully change ref of similar name' do
before do
project.repository.create_branch('dev')
project.repository.create_branch('development')
end
it 'switch ref from longer to shorter ref name' do
visit_blob('files/js/application.js', ref: 'development')
switch_ref_to('dev')
aggregate_failures do
expect(page.find('.file-title-name').text).to eq('application.js')
expect(page).not_to have_css('flash-container')
end
end
it 'switch ref from shorter to longer ref name' do
visit_blob('files/js/application.js', ref: 'dev')
switch_ref_to('development')
aggregate_failures do
expect(page.find('.file-title-name').text).to eq('application.js')
expect(page).not_to have_css('flash-container')
end
end
end
it 'successfully changes ref when the ref name matches the project name' do
project.repository.create_branch(project.name)
visit_blob('files/js/application.js', ref: project.name)
switch_ref_to('master')
aggregate_failures do
expect(page.find('.file-title-name').text).to eq('application.js')
expect(page).not_to have_css('flash-container')
end
end
end
context 'visiting with a line number anchor' do
before do
visit_blob('files/markdown/ruby-style-guide.md', anchor: 'L1')
end
it 'displays the blob using the simple viewer' do
aggregate_failures do
# hides the rich viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]')
expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
# highlights the line in question
expect(page).to have_selector('#LC1.hll')
# shows highlighted Markdown code
expect(page).to have_css(".js-syntax-highlight")
expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)")
# shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
end
end
end
end
context 'Markdown rendering' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add RedCarpet and CommonMark Markdown ",
file_path: 'files/commonmark/file.md',
file_content: "1. one\n - sublist\n"
).execute
end
context 'when rendering default markdown' do
before do
visit_blob('files/commonmark/file.md')
wait_for_requests
end
it 'renders using CommonMark' do
aggregate_failures do
expect(page).to have_content("sublist")
expect(page).not_to have_xpath("//ol//li//ul")
end
end
end
end
context 'Markdown file (stored in LFS)' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add Markdown in LFS",
file_path: 'files/lfs/file.md',
file_content: project.repository.blob_at('master', 'files/lfs/lfs_object.iso').data
).execute
end
context 'when LFS is enabled on the project' do
before do
allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
project.update_attribute(:lfs_enabled, true)
visit_blob('files/lfs/file.md')
wait_for_requests
end
it 'displays an error' do
aggregate_failures do
# hides the simple viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false)
expect(page).to have_selector('.blob-viewer[data-type="rich"]')
# shows an error message
expect(page).to have_content('The rendered file could not be displayed because it is stored in LFS. You can download it instead.')
# shows a viewer switcher
expect(page).to have_selector('.js-blob-viewer-switcher')
# does not show a copy button
expect(page).not_to have_selector('.js-copy-blob-source-btn')
# shows a download button
expect(page).to have_link('Download')
end
end
context 'switching to the simple viewer' do
before do
find('.js-blob-viewer-switcher .js-blob-viewer-switch-btn[data-viewer=simple]').click
wait_for_requests
end
it 'displays an error' do
aggregate_failures do
# hides the rich viewer
expect(page).to have_selector('.blob-viewer[data-type="simple"]')
expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false)
# shows an error message
expect(page).to have_content('The source could not be displayed because it is stored in LFS. You can download it instead.')
# does not show a copy button
expect(page).not_to have_selector('.js-copy-blob-source-btn')
end
end
end
end
context 'when LFS is disabled on the project' do
before do
visit_blob('files/lfs/file.md')
wait_for_requests
end
it 'displays the blob' do
aggregate_failures do
# shows text
expect(page).to have_content('size 1575078')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
# shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
# shows a raw button
expect(page).to have_link('Open raw')
end
end
end
end
context 'PDF file' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add PDF",
file_path: 'files/test.pdf',
file_content: project.repository.blob_at('add-pdf-file', 'files/pdf/test.pdf').data
).execute
visit_blob('files/test.pdf')
wait_for_requests
end
it 'displays the blob' do
aggregate_failures do
# shows rendered PDF
expect(page).to have_selector('.js-pdf-viewer')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
# does not show a copy button
expect(page).not_to have_selector('.js-copy-blob-source-btn')
# shows a download button
expect(page).to have_link('Download')
end
end
end
context 'Jupiter Notebook file' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add Jupiter Notebook",
file_path: 'files/basic.ipynb',
file_content: project.repository.blob_at('add-ipython-files', 'files/ipython/basic.ipynb').data
).execute
visit_blob('files/basic.ipynb')
wait_for_requests
end
it 'displays the blob' do
aggregate_failures do
# shows rendered notebook
expect(page).to have_selector('.js-notebook-viewer-mounted')
# does show a viewer switcher
expect(page).to have_selector('.js-blob-viewer-switcher')
# show a disabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
# shows a raw button
expect(page).to have_link('Open raw')
# shows a download button
expect(page).to have_link('Download')
# shows the rendered notebook
expect(page).to have_content('test')
end
end
end
context 'ISO file (stored in LFS)' do
context 'when LFS is enabled on the project' do
before do
allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
project.update_attribute(:lfs_enabled, true)
visit_blob('files/lfs/lfs_object.iso')
wait_for_requests
end
it 'displays the blob' do
aggregate_failures do
# shows a download link
expect(page).to have_link('Download (1.5 MB)')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
# does not show a copy button
expect(page).not_to have_selector('.js-copy-blob-source-btn')
# shows a download button
expect(page).to have_link('Download')
end
end
end
context 'when LFS is disabled on the project' do
before do
visit_blob('files/lfs/lfs_object.iso')
wait_for_requests
end
it 'displays the blob' do
aggregate_failures do
# shows text
expect(page).to have_content('size 1575078')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
# shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
# shows a raw button
expect(page).to have_link('Open raw')
end
end
end
end
context 'ZIP file' do
before do
visit_blob('Gemfile.zip')
wait_for_requests
end
it 'displays the blob' do
aggregate_failures do
# shows a download link
expect(page).to have_link('Download (2.11 KB)')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
# does not show a copy button
expect(page).not_to have_selector('.js-copy-blob-source-btn')
# shows a download button
expect(page).to have_link('Download')
end
end
end
context 'empty file' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add empty file",
file_path: 'files/empty.md',
file_content: ''
).execute
visit_blob('files/empty.md')
wait_for_requests
end
it 'displays an error' do
aggregate_failures do
# shows an error message
expect(page).to have_content('Empty file')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
# does not show a copy button
expect(page).not_to have_selector('.js-copy-blob-source-btn')
# does not show a download or raw button
expect(page).not_to have_link('Download')
expect(page).not_to have_link('Open raw')
end
end
end
context 'binary file that appears to be text in the first 1024 bytes' do
before do
visit_blob('encoding/binary-1.bin', ref: 'binary-encoding')
end
it 'displays the blob' do
aggregate_failures do
# shows a download link
expect(page).to have_link('Download (23.8 KB)')
# does not show a viewer switcher
expect(page).not_to have_selector('.js-blob-viewer-switcher')
# The specs below verify an arguably incorrect result, but since we only
# learn that the file is not actually text once the text viewer content
# is loaded asynchronously, there is no straightforward way to get these
# synchronously loaded elements to display correctly.
#
# Clicking the copy button will result in nothing being copied.
# Clicking the raw button will result in the binary file being downloaded,
# as expected.
# shows an enabled copy button, incorrectly
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
# shows a raw button, incorrectly
expect(page).to have_link('Open raw')
end
end
end
context 'files with auxiliary viewers' do
describe '.gitlab-ci.yml' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add .gitlab-ci.yml",
file_path: '.gitlab-ci.yml',
file_content: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
).execute
visit_blob('.gitlab-ci.yml')
end
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that configuration is valid
expect(page).to have_content('This GitLab CI configuration is valid.')
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
describe '.gitlab/route-map.yml' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add .gitlab/route-map.yml",
file_path: '.gitlab/route-map.yml',
file_content: <<-MAP.strip_heredoc
# Team data
- source: 'data/team.yml'
public: 'team/'
MAP
).execute
visit_blob('.gitlab/route-map.yml')
end
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that map is valid
expect(page).to have_content('This Route Map is valid.')
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
describe '.gitlab/dashboards/custom-dashboard.yml' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add .gitlab/dashboards/custom-dashboard.yml",
file_path: '.gitlab/dashboards/custom-dashboard.yml',
file_content: file_content
).execute
end
context 'with metrics_dashboard_exhaustive_validations feature flag off' do
before do
stub_feature_flags(metrics_dashboard_exhaustive_validations: false)
visit_blob('.gitlab/dashboards/custom-dashboard.yml')
end
context 'valid dashboard file' do
let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that dashboard yaml is valid
expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
context 'invalid dashboard file' do
let(:file_content) { "dashboard: 'invalid'" }
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that dashboard yaml is invalid
expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
expect(page).to have_content("panel_groups: should be an array of panel_groups objects")
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
end
context 'with metrics_dashboard_exhaustive_validations feature flag on' do
before do
stub_feature_flags(metrics_dashboard_exhaustive_validations: true)
visit_blob('.gitlab/dashboards/custom-dashboard.yml')
end
context 'valid dashboard file' do
let(:file_content) { File.read(Rails.root.join('config/prometheus/common_metrics.yml')) }
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that dashboard yaml is valid
expect(page).to have_content('Metrics Dashboard YAML definition is valid.')
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
context 'invalid dashboard file' do
let(:file_content) { "dashboard: 'invalid'" }
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows that dashboard yaml is invalid
expect(page).to have_content('Metrics Dashboard YAML definition is invalid:')
expect(page).to have_content("root is missing required keys: panel_groups")
# shows a learn more link
expect(page).to have_link('Learn more')
end
end
end
end
end
context 'LICENSE' do
before do
visit_blob('LICENSE')
end
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows license
expect(page).to have_content('This project is licensed under the MIT License.')
# shows a learn more link
expect(page).to have_link('Learn more', href: 'http://choosealicense.com/licenses/mit/')
end
end
end
context '*.gemspec' do
before do
project.add_maintainer(project.creator)
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add activerecord.gemspec",
file_path: 'activerecord.gemspec',
file_content: <<-SPEC.strip_heredoc
Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = "activerecord"
end
SPEC
).execute
visit_blob('activerecord.gemspec')
end
it 'displays an auxiliary viewer' do
aggregate_failures do
# shows names of dependency manager and package
expect(page).to have_content('This project manages its dependencies using RubyGems.')
# shows a learn more link
expect(page).to have_link('Learn more', href: 'https://rubygems.org/')
end
end
end
context 'CONTRIBUTING.md' do
before do
file_name = 'CONTRIBUTING.md'
create_file(file_name, '## Contribution guidelines')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("After you've reviewed these contribution guidelines, you'll be all set to contribute to this project.")
end
end
end
context 'CHANGELOG.md' do
before do
file_name = 'CHANGELOG.md'
create_file(file_name, '## Changelog for v1.0.0')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("To find the state of this project's repository at the time of any of these versions, check out the tags.")
end
end
end
context 'Cargo.toml' do
before do
file_name = 'Cargo.toml'
create_file(file_name, '
[package]
name = "hello_world" # the name of the package
version = "0.1.0" # the current version, obeying semver
authors = ["Alice <a@example.com>", "Bob <b@example.com>"]
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Cargo.")
end
end
end
context 'Cartfile' do
before do
file_name = 'Cartfile'
create_file(file_name, '
gitlab "Alamofire/Alamofire" == 4.9.0
gitlab "Alamofire/AlamofireImage" ~> 3.4
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Carthage.")
end
end
end
context 'composer.json' do
before do
file_name = 'composer.json'
create_file(file_name, '
{
"license": "MIT"
}
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Composer.")
end
end
end
context 'Gemfile' do
before do
file_name = 'Gemfile'
create_file(file_name, '
source "https://rubygems.org"
# Gems here
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Bundler.")
end
end
end
context 'Godeps.json' do
before do
file_name = 'Godeps.json'
create_file(file_name, '
{
"GoVersion": "go1.6"
}
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using godep.")
end
end
end
context 'go.mod' do
before do
file_name = 'go.mod'
create_file(file_name, '
module example.com/mymodule
go 1.14
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Go Modules.")
end
end
end
context 'package.json' do
before do
file_name = 'package.json'
create_file(file_name, '
{
"name": "my-awesome-package",
"version": "1.0.0"
}
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using npm.")
end
end
end
context 'podfile' do
before do
file_name = 'podfile'
create_file(file_name, 'platform :ios, "8.0"')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using CocoaPods.")
end
end
end
context 'test.podspec' do
before do
file_name = 'test.podspec'
create_file(file_name, '
Pod::Spec.new do |s|
s.name = "TensorFlowLiteC"
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using CocoaPods.")
end
end
end
context 'JSON.podspec.json' do
before do
file_name = 'JSON.podspec.json'
create_file(file_name, '
{
"name": "JSON"
}
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using CocoaPods.")
end
end
end
context 'requirements.txt' do
before do
file_name = 'requirements.txt'
create_file(file_name, 'Project requirements')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using pip.")
end
end
end
context 'yarn.lock' do
before do
file_name = 'yarn.lock'
create_file(file_name, '
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
')
visit_blob(file_name)
end
it 'displays an auxiliary viewer' do
aggregate_failures do
expect(page).to have_content("This project manages its dependencies using Yarn.")
end
end
end
end
context 'realtime pipelines' do
before do
Files::CreateService.new(
project,
project.creator,
start_branch: 'feature',
branch_name: 'feature',
commit_message: "Add ruby file",
file_path: 'files/ruby/test.rb',
file_content: "# Awesome content"
).execute
create(:ci_pipeline, status: 'running', project: project, ref: 'feature', sha: project.commit('feature').sha)
visit_blob('files/ruby/test.rb', ref: 'feature')
end
it 'shows the realtime pipeline status' do
page.within('.commit-actions') do
expect(page).to have_css('.ci-status-icon')
expect(page).to have_css('.ci-status-icon-running')
expect(page).to have_css('.js-ci-status-icon-running')
end
end
end
context 'for subgroups' do
let(:group) { create(:group) }
let(:subgroup) { create(:group, parent: group) }
let(:project) { create(:project, :public, :repository, group: subgroup) }
it 'renders tree table without errors' do
visit_blob('README.md')
expect(page).to have_selector('.file-content')
expect(page).not_to have_selector('[data-testid="alert-danger"]')
end
it 'displays a GPG badge' do
visit_blob('CONTRIBUTING.md', ref: '33f3729a45c02fc67d00adb1b8bca394b0e761d9')
expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
expect(page).to have_selector '.gpg-status-box.invalid'
end
end
context 'on signed merge commit' do
it 'displays a GPG badge' do
visit_blob('conflicting-file.md', ref: '6101e87e575de14b38b4e1ce180519a813671e10')
expect(page).not_to have_selector '.gpg-status-box.js-loading-gpg-badge'
expect(page).to have_selector '.gpg-status-box.invalid'
end
end
context 'when static objects external storage is enabled' do
before do
stub_application_setting(static_objects_external_storage_url: 'https://cdn.gitlab.com')
end
context 'private project' do
let_it_be(:project) { create(:project, :repository, :private) }
let_it_be(:user) { create(:user) }
before do
project.add_developer(user)
sign_in(user)
visit_blob('README.md')
end
it 'shows open raw and download buttons with external storage URL prepended and user token appended to their href' do
path = project_raw_path(project, 'master/README.md')
raw_uri = "https://cdn.gitlab.com#{path}?token=#{user.static_object_token}"
download_uri = "https://cdn.gitlab.com#{path}?inline=false&token=#{user.static_object_token}"
aggregate_failures do
expect(page).to have_link 'Open raw', href: raw_uri
expect(page).to have_link 'Download', href: download_uri
end
end
end
context 'public project' do
before do
visit_blob('README.md')
end
it 'shows open raw and download buttons with external storage URL prepended to their href' do
path = project_raw_path(project, 'master/README.md')
raw_uri = "https://cdn.gitlab.com#{path}"
download_uri = "https://cdn.gitlab.com#{path}?inline=false"
aggregate_failures do
expect(page).to have_link 'Open raw', href: raw_uri
expect(page).to have_link 'Download', href: download_uri
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Editing file blob', :js do
include TreeHelper
include BlobSpecHelpers
let(:project) { create(:project, :public, :repository) }
let(:merge_request) { create(:merge_request, source_project: project, source_branch: 'feature', target_branch: 'master') }
let(:branch) { 'master' }
let(:file_path) { project.repository.ls_files(project.repository.root_ref)[1] }
let(:readme_file_path) { 'README.md' }
before do
stub_feature_flags(refactor_blob_viewer: false)
end
context 'as a developer' do
let(:user) { create(:user) }
let(:role) { :developer }
before do
project.add_role(user, role)
sign_in(user)
end
def edit_and_commit(commit_changes: true, is_diff: false)
set_default_button('edit')
refresh
wait_for_requests
if is_diff
first('.js-diff-more-actions').click
click_link('Edit in single-file editor')
else
click_link('Edit')
end
fill_editor(content: 'class NextFeature\\nend\\n')
if commit_changes
click_button 'Commit changes'
end
end
def fill_editor(content: 'class NextFeature\\nend\\n')
wait_for_requests
execute_script("monaco.editor.getModels()[0].setValue('#{content}')")
end
context 'from MR diff' do
before do
visit diffs_project_merge_request_path(project, merge_request)
edit_and_commit(is_diff: true)
end
it 'returns me to the mr' do
expect(page).to have_content(merge_request.title)
end
end
it 'updates the content of file with a number as file path' do
project.repository.create_file(user, '1', 'test', message: 'testing', branch_name: branch)
visit project_blob_path(project, tree_join(branch, '1'))
edit_and_commit
expect(page).to have_content 'NextFeature'
end
it 'editing a template file in a sub directory does not change path' do
project.repository.create_file(user, 'ci/.gitlab-ci.yml', 'test', message: 'testing', branch_name: branch)
visit project_edit_blob_path(project, tree_join(branch, 'ci/.gitlab-ci.yml'))
expect(find_by_id('file_path').value).to eq('ci/.gitlab-ci.yml')
end
it 'updating file path updates syntax highlighting' do
visit project_edit_blob_path(project, tree_join(branch, readme_file_path))
expect(find('#editor')['data-mode-id']).to eq('markdown')
find('#file_path').send_keys('foo.txt') do
expect(find('#editor')['data-mode-id']).to eq('plaintext')
end
end
context 'from blob file path' do
before do
visit project_blob_path(project, tree_join(branch, file_path))
end
it 'updates content' do
edit_and_commit
expect(page).to have_content 'successfully committed'
expect(page).to have_content 'NextFeature'
end
it 'previews content' do
edit_and_commit(commit_changes: false)
click_link 'Preview changes'
wait_for_requests
old_line_count = page.all('.line_holder.old').size
new_line_count = page.all('.line_holder.new').size
expect(old_line_count).to be > 0
expect(new_line_count).to be > 0
end
end
context 'when rendering the preview' do
it 'renders content with CommonMark' do
visit project_edit_blob_path(project, tree_join(branch, readme_file_path))
fill_editor(content: '1. one\\n - sublist\\n')
click_link 'Preview'
wait_for_requests
# the above generates two separate lists (not embedded) in CommonMark
expect(page).to have_content('sublist')
expect(page).not_to have_xpath('//ol//li//ul')
end
end
end
context 'visit blob edit' do
context 'redirects to sign in and returns' do
context 'as developer' do
let(:user) { create(:user) }
before do
project.add_developer(user)
visit project_edit_blob_path(project, tree_join(branch, file_path))
end
it 'redirects to sign in and returns' do
expect(page).to have_current_path(new_user_session_path)
gitlab_sign_in(user)
expect(page).to have_current_path(project_edit_blob_path(project, tree_join(branch, file_path)))
end
end
context 'as guest' do
let(:user) { create(:user) }
before do
visit project_edit_blob_path(project, tree_join(branch, file_path))
end
it 'redirects to sign in and returns' do
expect(page).to have_current_path(new_user_session_path)
gitlab_sign_in(user)
expect(page).to have_current_path(project_blob_path(project, tree_join(branch, file_path)))
end
end
end
context 'as developer' do
let(:user) { create(:user) }
let(:protected_branch) { 'protected-branch' }
before do
project.add_developer(user)
project.repository.add_branch(user, protected_branch, 'master')
create(:protected_branch, project: project, name: protected_branch)
sign_in(user)
end
context 'on some branch' do
before do
visit project_edit_blob_path(project, tree_join(branch, file_path))
end
it 'shows blob editor with same branch' do
expect(page).to have_current_path(project_edit_blob_path(project, tree_join(branch, file_path)))
expect(find('.js-branch-name').value).to eq(branch)
end
end
context 'with protected branch' do
it 'shows blob editor with patch branch' do
freeze_time do
visit project_edit_blob_path(project, tree_join(protected_branch, file_path))
epoch = Time.zone.now.strftime('%s%L').last(5)
expect(find('.js-branch-name').value).to eq "#{user.username}-protected-branch-patch-#{epoch}"
end
end
end
end
context 'as maintainer' do
let(:user) { create(:user) }
before do
project.add_maintainer(user)
sign_in(user)
visit project_edit_blob_path(project, tree_join(branch, file_path))
end
it 'shows blob editor with same branch' do
expect(page).to have_current_path(project_edit_blob_path(project, tree_join(branch, file_path)))
expect(find('.js-branch-name').value).to eq(branch)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Blob shortcuts', :js do
include TreeHelper
let(:project) { create(:project, :public, :repository) }
let(:path) { project.repository.ls_files(project.repository.root_ref)[0] }
let(:sha) { project.repository.commit.sha }
before do
stub_feature_flags(refactor_blob_viewer: false)
end
describe 'On a file(blob)', :js do
def get_absolute_url(path = "")
"http://#{page.server.host}:#{page.server.port}#{path}"
end
def visit_blob(fragment = nil)
visit project_blob_path(project, tree_join('master', path), anchor: fragment)
end
describe 'pressing "y"' do
it 'redirects to permalink with commit sha' do
visit_blob
wait_for_requests
find('body').native.send_key('y')
expect(page).to have_current_path(get_absolute_url(project_blob_path(project, tree_join(sha, path))), url: true)
end
it 'maintains fragment hash when redirecting' do
fragment = "L1"
visit_blob(fragment)
wait_for_requests
find('body').native.send_key('y')
expect(page).to have_current_path(get_absolute_url(project_blob_path(project, tree_join(sha, path), anchor: fragment)), url: true)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'User creates new blob', :js do
include WebIdeSpecHelpers
let(:user) { create(:user) }
let(:project) { create(:project, :empty_repo) }
before do
stub_feature_flags(refactor_blob_viewer: false)
end
shared_examples 'creating a file' do
it 'allows the user to add a new file in Web IDE' do
visit project_path(project)
click_link 'New file'
wait_for_requests
ide_create_new_file('dummy-file', content: "Hello world\n")
ide_commit
expect(page).to have_content('All changes are committed')
expect(project.repository.blob_at('master', 'dummy-file').data).to eql("Hello world\n")
end
end
describe 'as a maintainer' do
before do
project.add_maintainer(user)
sign_in(user)
end
it_behaves_like 'creating a file'
end
describe 'as an admin' do
let(:user) { create(:user, :admin) }
before do
sign_in(user)
gitlab_enable_admin_mode_sign_in(user)
end
it_behaves_like 'creating a file'
end
describe 'as a developer' do
before do
project.add_developer(user)
sign_in(user)
visit project_path(project)
end
it 'does not allow pushing to the default branch' do
expect(page).not_to have_content('New file')
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'User follows pipeline suggest nudge spec when feature is enabled', :js do
include CookieHelper
let(:project) { create(:project, :empty_repo) }
let(:user) { project.first_owner }
before do
stub_feature_flags(refactor_blob_viewer: false)
end
describe 'viewing the new blob page' do
before do
sign_in(user)
end
context 'when the page is loaded from the link using the suggest_gitlab_ci_yml param' do
before do
visit namespace_project_new_blob_path(namespace_id: project.namespace, project_id: project, id: 'master', suggest_gitlab_ci_yml: 'true')
end
it 'pre-fills .gitlab-ci.yml for file name' do
file_name = page.find_by_id('file_name')
expect(file_name.value).to have_content('.gitlab-ci.yml')
end
it 'chooses the .gitlab-ci.yml Template Type' do
template_type = page.find(:css, '.template-type-selector .dropdown-toggle-text')
expect(template_type.text).to have_content('.gitlab-ci.yml')
end
it 'displays suggest_gitlab_ci_yml popover' do
page.find(:css, '.gitlab-ci-yml-selector').click
popover_selector = '.suggest-gitlab-ci-yml'
expect(page).to have_css(popover_selector, visible: true)
page.within(popover_selector) do
expect(page).to have_content('1/2: Choose a template')
end
end
it 'sets the commit cookie when the Commit button is clicked' do
click_button 'Commit changes'
expect(get_cookie("suggest_gitlab_ci_yml_commit_#{project.id}")).to be_present
end
end
context 'when the page is visited without the param' do
before do
visit namespace_project_new_blob_path(namespace_id: project.namespace, project_id: project, id: 'master')
end
it 'does not pre-fill .gitlab-ci.yml for file name' do
file_name = page.find_by_id('file_name')
expect(file_name.value).not_to have_content('.gitlab-ci.yml')
end
it 'does not choose the .gitlab-ci.yml Template Type' do
template_type = page.find(:css, '.template-type-selector .dropdown-toggle-text')
expect(template_type.text).to have_content('Select a template type')
end
it 'does not display suggest_gitlab_ci_yml popover' do
popover_selector = '.b-popover.suggest-gitlab-ci-yml'
expect(page).not_to have_css(popover_selector, visible: true)
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'User views pipeline editor button on root ci config file', :js do
include BlobSpecHelpers
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public, :repository) }
before do
stub_feature_flags(refactor_blob_viewer: false)
end
context "when the ci config is the root file" do
before do
project.add_developer(user)
sign_in(user)
end
it 'shows the button to the Pipeline Editor' do
project.update!(ci_config_path: '.my-config.yml')
project.repository.create_file(user, project.ci_config_path_or_default, 'test', message: 'testing', branch_name: 'master')
visit project_blob_path(project, File.join('master', '.my-config.yml'))
expect(page).to have_content('Edit in pipeline editor')
end
it 'does not shows the Pipeline Editor button' do
project.repository.create_file(user, '.my-sub-config.yml', 'test', message: 'testing', branch_name: 'master')
visit project_blob_path(project, File.join('master', '.my-sub-config.yml'))
expect(page).not_to have_content('Edit in pipeline editor')
end
end
context "when user cannot collaborate" do
before do
sign_in(user)
end
it 'does not shows the Pipeline Editor button' do
visit project_blob_path(project, File.join('master', '.my-config.yml'))
expect(page).not_to have_content('Edit in pipeline editor')
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Projects > Files > User wants to edit a file' do
let(:project) { create(:project, :repository) }
let(:user) { project.first_owner }
let(:commit_params) do
{
start_branch: project.default_branch,
branch_name: project.default_branch,
commit_message: "Committing First Update",
file_path: ".gitignore",
file_content: "First Update",
last_commit_sha: Gitlab::Git::Commit.last_for_path(project.repository, project.default_branch,
".gitignore").sha
}
end
before do
stub_feature_flags(refactor_blob_viewer: false)
sign_in user
visit project_edit_blob_path(project,
File.join(project.default_branch, '.gitignore'))
end
it 'file has been updated since the user opened the edit page' do
Files::UpdateService.new(project, user, commit_params).execute
click_button 'Commit changes'
expect(page).to have_content 'Someone edited the file the same time you did.'
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Projects > Files > Find file keyboard shortcuts', :js do
let(:project) { create(:project, :repository) }
let(:user) { project.first_owner }
before do
stub_feature_flags(refactor_blob_viewer: false)
sign_in user
visit project_find_file_path(project, project.repository.root_ref)
wait_for_requests
end
it 'opens file when pressing enter key' do
fill_in 'file_find', with: 'CHANGELOG'
find('#file_find').native.send_keys(:enter)
expect(page).to have_selector('.blob-content-holder')
page.within('.js-file-title') do
expect(page).to have_content('CHANGELOG')
end
end
it 'navigates files with arrow keys' do
fill_in 'file_find', with: 'application.'
find('#file_find').native.send_keys(:down)
find('#file_find').native.send_keys(:enter)
expect(page).to have_selector('.blob-content-holder')
page.within('.js-file-title') do
expect(page).to have_content('application.js')
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Projects > Files > Project owner creates a license file', :js do
let(:project) { create(:project, :repository) }
let(:project_maintainer) { project.first_owner }
before do
stub_feature_flags(refactor_blob_viewer: false)
project.repository.delete_file(project_maintainer, 'LICENSE',
message: 'Remove LICENSE', branch_name: 'master')
sign_in(project_maintainer)
visit project_path(project)
end
it 'project maintainer creates a license file manually from a template' do
visit project_tree_path(project, project.repository.root_ref)
find('.add-to-tree').click
click_link 'New file'
fill_in :file_name, with: 'LICENSE'
expect(page).to have_selector('.license-selector')
select_template('MIT License')
file_content = first('.file-editor')
expect(file_content).to have_content('MIT License')
expect(file_content).to have_content("Copyright (c) #{Time.zone.now.year} #{project.namespace.human_name}")
fill_in :commit_message, with: 'Add a LICENSE file', visible: true
click_button 'Commit changes'
expect(page).to have_current_path(
project_blob_path(project, 'master/LICENSE'), ignore_query: true)
expect(page).to have_content('MIT License')
expect(page).to have_content("Copyright (c) #{Time.zone.now.year} #{project.namespace.human_name}")
end
it 'project maintainer creates a license file from the "Add license" link' do
click_link 'Add LICENSE'
expect(page).to have_content('New file')
expect(page).to have_current_path(
project_new_blob_path(project, 'master'), ignore_query: true)
expect(find('#file_name').value).to eq('LICENSE')
expect(page).to have_selector('.license-selector')
select_template('MIT License')
file_content = first('.file-editor')
expect(file_content).to have_content('MIT License')
expect(file_content).to have_content("Copyright (c) #{Time.zone.now.year} #{project.namespace.human_name}")
fill_in :commit_message, with: 'Add a LICENSE file', visible: true
click_button 'Commit changes'
expect(page).to have_current_path(
project_blob_path(project, 'master/LICENSE'), ignore_query: true)
expect(page).to have_content('MIT License')
expect(page).to have_content("Copyright (c) #{Time.zone.now.year} #{project.namespace.human_name}")
end
def select_template(template)
page.within('.js-license-selector-wrap') do
click_button 'Apply a template'
click_link template
wait_for_requests
end
end
end
# frozen_string_literal: true
require "spec_helper"
RSpec.describe "User browses files", :js do
include RepoHelpers
let(:fork_message) do
"You're not allowed to make changes to this project directly. "\
"A fork of this project has been created that you can make changes in, so you can submit a merge request."
end
let(:project) { create(:project, :repository, name: "Shop") }
let(:project2) { create(:project, :repository, name: "Another Project", path: "another-project") }
let(:tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
let(:user) { project.first_owner }
before do
stub_feature_flags(refactor_blob_viewer: false)
sign_in(user)
end
it "shows last commit for current directory", :js do
visit(tree_path_root_ref)
click_link("files")
last_commit = project.repository.last_commit_for_path(project.default_branch, "files")
page.within(".commit-detail") do
expect(page).to have_content(last_commit.short_id).and have_content(last_commit.author_name)
end
end
context "when browsing the master branch", :js do
before do
visit(tree_path_root_ref)
end
it "shows files from a repository" do
expect(page).to have_content("VERSION")
.and have_content(".gitignore")
.and have_content("LICENSE")
end
it "shows the `Browse Directory` link" do
click_link("files")
page.within('.repo-breadcrumb') do
expect(page).to have_link('files')
end
click_link("History")
expect(page).to have_link("Browse Directory").and have_no_link("Browse Code")
end
it "shows the `Browse File` link" do
page.within(".tree-table") do
click_link("README.md")
end
click_link("History")
expect(page).to have_link("Browse File").and have_no_link("Browse Files")
end
it "shows the `Browse Files` link" do
click_link("History")
expect(page).to have_link("Browse Files").and have_no_link("Browse Directory")
end
it "redirects to the permalink URL" do
click_link(".gitignore")
click_link("Permalink")
permalink_path = project_blob_path(project, "#{project.repository.commit.sha}/.gitignore")
expect(page).to have_current_path(permalink_path, ignore_query: true)
end
end
context "when browsing the `markdown` branch", :js do
context "when browsing the root" do
before do
visit(project_tree_path(project, "markdown"))
end
it "shows correct files and links" do
expect(page).to have_current_path(project_tree_path(project, "markdown"), ignore_query: true)
expect(page).to have_content("README.md")
.and have_content("CHANGELOG")
.and have_content("Welcome to GitLab GitLab is a free project and repository management application")
.and have_link("GitLab API doc")
.and have_link("GitLab API website")
.and have_link("Rake tasks")
.and have_link("backup and restore procedure")
.and have_link("GitLab API doc directory")
.and have_link("Maintenance")
.and have_header_with_correct_id_and_link(2, "Application details", "application-details")
.and have_link("empty", href: "")
.and have_link("#id", href: "#id")
.and have_link("/#id", href: project_blob_path(project, "markdown/README.md", anchor: "id"))
.and have_link("README.md#id", href: project_blob_path(project, "markdown/README.md", anchor: "id"))
.and have_link("d/README.md#id", href: project_blob_path(project, "markdown/db/README.md", anchor: "id"))
end
it "shows correct content of file" do
click_link("GitLab API doc")
expect(page).to have_current_path(project_blob_path(project, "markdown/doc/api/README.md"), ignore_query: true)
expect(page).to have_content("All API requests require authentication")
.and have_content("Contents")
.and have_link("Users")
.and have_link("Rake tasks")
.and have_header_with_correct_id_and_link(1, "GitLab API", "gitlab-api")
click_link("Users")
expect(page).to have_current_path(project_blob_path(project, "markdown/doc/api/users.md"), ignore_query: true)
expect(page).to have_content("Get a list of users.")
page.go_back
click_link("Rake tasks")
expect(page).to have_current_path(project_tree_path(project, "markdown/doc/raketasks"), ignore_query: true)
expect(page).to have_content("backup_restore.md").and have_content("maintenance.md")
click_link("maintenance.md")
expect(page).to have_current_path(project_blob_path(project, "markdown/doc/raketasks/maintenance.md"), ignore_query: true)
expect(page).to have_content("bundle exec rake gitlab:env:info RAILS_ENV=production")
click_link("shop")
page.within(".tree-table") do
click_link("README.md")
end
page.go_back
page.within(".tree-table") do
click_link("d")
end
expect(page).to have_link("..", href: project_tree_path(project, "markdown/"))
page.within(".tree-table") do
click_link("README.md")
end
expect(page).to have_link("empty", href: "")
end
it "shows correct content of directory" do
click_link("GitLab API doc directory")
expect(page).to have_current_path(project_tree_path(project, "markdown/doc/api"), ignore_query: true)
expect(page).to have_content("README.md").and have_content("users.md")
click_link("Users")
expect(page).to have_current_path(project_blob_path(project, "markdown/doc/api/users.md"), ignore_query: true)
expect(page).to have_content("List users").and have_content("Get a list of users.")
end
end
end
context 'when commit message has markdown', :js do
before do
project.repository.create_file(user, 'index', 'test', message: ':star: testing', branch_name: 'master')
visit(project_tree_path(project, "master"))
end
it 'renders emojis' do
expect(page).to have_selector('gl-emoji', count: 2)
end
end
context "when browsing a `improve/awesome` branch", :js do
before do
visit(project_tree_path(project, "improve/awesome"))
end
it "shows files from a repository" do
expect(page).to have_content("VERSION")
.and have_content(".gitignore")
.and have_content("LICENSE")
click_link("files")
page.within('.repo-breadcrumb') do
expect(page).to have_link('files')
end
click_link("html")
page.within('.repo-breadcrumb') do
expect(page).to have_link('html')
end
expect(page).to have_link('500.html')
end
end
context "when browsing a `Ääh-test-utf-8` branch", :js do
before do
project.repository.create_branch('Ääh-test-utf-8', project.repository.root_ref)
visit(project_tree_path(project, "Ääh-test-utf-8"))
end
it "shows files from a repository" do
expect(page).to have_content("VERSION")
.and have_content(".gitignore")
.and have_content("LICENSE")
click_link("files")
page.within('.repo-breadcrumb') do
expect(page).to have_link('files')
end
click_link("html")
page.within('.repo-breadcrumb') do
expect(page).to have_link('html')
end
expect(page).to have_link('500.html')
end
end
context "when browsing a `test-#` branch", :js do
before do
project.repository.create_branch('test-#', project.repository.root_ref)
visit(project_tree_path(project, "test-#"))
end
it "shows files from a repository" do
expect(page).to have_content("VERSION")
.and have_content(".gitignore")
.and have_content("LICENSE")
click_link("files")
page.within('.repo-breadcrumb') do
expect(page).to have_link('files')
end
click_link("html")
page.within('.repo-breadcrumb') do
expect(page).to have_link('html')
end
expect(page).to have_link('500.html')
end
end
context "when browsing a specific ref", :js do
let(:ref) { project_tree_path(project, "6d39438") }
before do
visit(ref)
end
it "shows files from a repository for `6d39438`" do
expect(page).to have_current_path(ref, ignore_query: true)
expect(page).to have_content(".gitignore").and have_content("LICENSE")
end
it "shows files from a repository with apostroph in its name" do
first(".js-project-refs-dropdown").click
page.within(".project-refs-form") do
click_link("'test'")
end
expect(page).to have_selector(".dropdown-toggle-text", text: "'test'")
visit(project_tree_path(project, "'test'"))
expect(page).not_to have_selector(".tree-commit .animation-container")
end
it "shows the code with a leading dot in the directory" do
first(".js-project-refs-dropdown").click
page.within(".project-refs-form") do
click_link("fix")
end
visit(project_tree_path(project, "fix/.testdir"))
expect(page).not_to have_selector(".tree-commit .animation-container")
end
it "does not show the permalink link" do
click_link(".gitignore")
expect(page).not_to have_link("permalink")
end
end
context "when browsing a file content", :js do
before do
visit(tree_path_root_ref)
wait_for_requests
click_link(".gitignore")
end
it "shows a file content" do
expect(page).to have_content("*.rbc")
end
it "is possible to blame" do
click_link("Blame")
expect(page).to have_content("*.rb")
.and have_content("Dmitriy Zaporozhets")
.and have_content("Initial commit")
.and have_content("Ignore DS files")
previous_commit_anchor = "//a[@title='Ignore DS files']/parent::span/following-sibling::span/a"
find(:xpath, previous_commit_anchor).click
expect(page).to have_content("*.rb")
.and have_content("Dmitriy Zaporozhets")
.and have_content("Initial commit")
expect(page).not_to have_content("Ignore DS files")
end
end
context "when browsing a file with pathspec characters" do
let(:filename) { ':wq' }
let(:newrev) { project.repository.commit('master').sha }
before do
create_file_in_repo(project, 'master', 'master', filename, 'Test file')
path = File.join('master', filename)
visit(project_blob_path(project, path))
wait_for_requests
end
it "shows raw file content in a new tab" do
new_tab = window_opened_by {click_link 'Open raw'}
within_window new_tab do
expect(page).to have_content("Test file")
end
end
end
context "when browsing a raw file" do
before do
visit(tree_path_root_ref)
wait_for_requests
click_link(".gitignore")
wait_for_requests
end
it "shows raw file content in a new tab" do
new_tab = window_opened_by {click_link 'Open raw'}
within_window new_tab do
expect(page).to have_content("*.rbc")
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Projects > Files > User browses LFS files' do
let(:project) { create(:project, :repository) }
let(:user) { project.first_owner }
before do
stub_feature_flags(refactor_blob_viewer: false)
sign_in(user)
end
context 'when LFS is disabled', :js do
before do
allow_next_found_instance_of(Project) do |project|
allow(project).to receive(:lfs_enabled?).and_return(false)
end
visit project_tree_path(project, 'lfs')
wait_for_requests
end
it 'is possible to see raw content of LFS pointer' do
click_link 'files'
page.within('.repo-breadcrumb') do
expect(page).to have_link('files')
end
click_link 'lfs'
page.within('.repo-breadcrumb') do
expect(page).to have_link('lfs')
end
click_link 'lfs_object.iso'
expect(page).to have_content 'version https://git-lfs.github.com/spec/v1'
expect(page).to have_content 'oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897'
expect(page).to have_content 'size 1575078'
expect(page).not_to have_content 'Download (1.5 MB)'
end
end
context 'when LFS is enabled', :js do
before do
allow_next_found_instance_of(Project) do |project|
allow(project).to receive(:lfs_enabled?).and_return(true)
end
visit project_tree_path(project, 'lfs')
wait_for_requests
end
it 'shows an LFS object' do
click_link('files')
page.within('.repo-breadcrumb') do
expect(page).to have_link('files')
end
click_link('lfs')
click_link('lfs_object.iso')
expect(page).to have_content('Download (1.5 MB)')
expect(page).not_to have_content('version https://git-lfs.github.com/spec/v1')
expect(page).not_to have_content('oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897')
expect(page).not_to have_content('size 1575078')
page.within('.content') do
expect(page).to have_content('Delete')
expect(page).to have_content('History')
expect(page).to have_content('Permalink')
expect(page).to have_content('Replace')
expect(page).to have_link('Download')
expect(page).not_to have_content('Annotate')
expect(page).not_to have_content('Blame')
expect(page).not_to have_selector(:link_or_button, text: /^Edit$/)
expect(page).to have_selector(:link_or_button, 'Open in Web IDE')
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Projects > Files > User deletes files', :js do
let(:fork_message) do
"You're not allowed to make changes to this project directly. "\
"A fork of this project has been created that you can make changes in, so you can submit a merge request."
end
let(:project) { create(:project, :repository, name: 'Shop') }
let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
let(:user) { create(:user) }
before do
stub_feature_flags(refactor_blob_viewer: false)
sign_in(user)
end
context 'when an user has write access' do
before do
project.add_maintainer(user)
visit(project_tree_path_root_ref)
wait_for_requests
end
it 'deletes the file', :js do
click_link('.gitignore')
expect(page).to have_content('.gitignore')
click_on('Delete')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Delete file')
expect(page).to have_current_path(project_tree_path(project, 'master/'), ignore_query: true)
expect(page).not_to have_content('.gitignore')
end
end
context 'when an user does not have write access', :js do
before do
project2.add_reporter(user)
visit(project2_tree_path_root_ref)
wait_for_requests
end
it 'deletes the file in a forked project', :js, :sidekiq_might_not_need_inline do
click_link('.gitignore')
expect(page).to have_content('.gitignore')
click_on('Delete')
expect(page).to have_link('Fork')
expect(page).to have_button('Cancel')
click_link('Fork')
expect(page).to have_content(fork_message)
click_on('Delete')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Delete file')
fork = user.fork_of(project2.reload)
expect(page).to have_current_path(project_new_merge_request_path(fork), ignore_query: true)
expect(page).to have_content('New commit message')
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Projects > Files > User edits files', :js do
include ProjectForksHelper
include BlobSpecHelpers
let(:project) { create(:project, :repository, name: 'Shop') }
let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
let(:user) { create(:user) }
before do
stub_feature_flags(refactor_blob_viewer: false)
sign_in(user)
end
after do
unset_default_button
end
shared_examples 'unavailable for an archived project' do
it 'does not show the edit link for an archived project', :js do
project.update!(archived: true)
visit project_tree_path(project, project.repository.root_ref)
click_link('.gitignore')
aggregate_failures 'available edit buttons' do
expect(page).not_to have_text('Edit')
expect(page).not_to have_text('Web IDE')
expect(page).not_to have_text('Replace')
expect(page).not_to have_text('Delete')
end
end
end
context 'when an user has write access', :js do
before do
project.add_maintainer(user)
visit(project_tree_path_root_ref)
wait_for_requests
end
it 'inserts a content of a file' do
set_default_button('edit')
click_link('.gitignore')
click_link_or_button('Edit')
find('.file-editor', match: :first)
find('#editor')
set_editor_value('*.rbca')
expect(editor_value).to eq('*.rbca')
end
it 'does not show the edit link if a file is binary' do
binary_file = File.join(project.repository.root_ref, 'files/images/logo-black.png')
visit(project_blob_path(project, binary_file))
wait_for_requests
page.within '.content' do
expect(page).not_to have_link('edit')
end
end
it 'commits an edited file' do
set_default_button('edit')
click_link('.gitignore')
click_link_or_button('Edit')
find('.file-editor', match: :first)
find('#editor')
set_editor_value('*.rbca')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
expect(page).to have_current_path(project_blob_path(project, 'master/.gitignore'), ignore_query: true)
wait_for_requests
expect(page).to have_content('*.rbca')
end
it 'commits an edited file to a new branch' do
set_default_button('edit')
click_link('.gitignore')
click_link_or_button('Edit')
find('.file-editor', match: :first)
find('#editor')
set_editor_value('*.rbca')
fill_in(:commit_message, with: 'New commit message', visible: true)
fill_in(:branch_name, with: 'new_branch_name', visible: true)
click_button('Commit changes')
expect(page).to have_current_path(project_new_merge_request_path(project), ignore_query: true)
click_link('Changes')
expect(page).to have_content('*.rbca')
end
it 'shows the diff of an edited file' do
set_default_button('edit')
click_link('.gitignore')
click_link_or_button('Edit')
find('.file-editor', match: :first)
find('#editor')
set_editor_value('*.rbca')
click_link('Preview changes')
expect(page).to have_css('.line_holder.new')
end
it_behaves_like 'unavailable for an archived project'
end
context 'when an user does not have write access', :js do
before do
project2.add_reporter(user)
visit(project2_tree_path_root_ref)
wait_for_requests
end
def expect_fork_prompt
expect(page).to have_selector(:link_or_button, 'Fork')
expect(page).to have_selector(:link_or_button, 'Cancel')
expect(page).to have_content(
"You can’t edit files directly in this project. "\
"Fork this project and submit a merge request with your changes."
)
end
def expect_fork_status
expect(page).to have_content(
"You're not allowed to make changes to this project directly. "\
"A fork of this project has been created that you can make changes in, so you can submit a merge request."
)
end
it 'inserts a content of a file in a forked project', :sidekiq_might_not_need_inline do
set_default_button('edit')
click_link('.gitignore')
click_link_or_button('Edit')
expect_fork_prompt
click_link_or_button('Fork project')
expect_fork_status
find('.file-editor', match: :first)
find('#editor')
set_editor_value('*.rbca')
expect(editor_value).to eq('*.rbca')
end
it 'commits an edited file in a forked project', :sidekiq_might_not_need_inline do
set_default_button('edit')
click_link('.gitignore')
click_link_or_button('Edit')
expect_fork_prompt
click_link_or_button('Fork project')
find('.file-editor', match: :first)
find('#editor')
set_editor_value('*.rbca')
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Commit changes')
fork = user.fork_of(project2.reload)
expect(page).to have_current_path(project_new_merge_request_path(fork), ignore_query: true)
wait_for_requests
expect(page).to have_content('New commit message')
end
context 'when the user already had a fork of the project', :js do
let!(:forked_project) { fork_project(project2, user, namespace: user.namespace, repository: true) }
before do
visit(project2_tree_path_root_ref)
wait_for_requests
end
it 'links to the forked project for editing', :sidekiq_might_not_need_inline do
set_default_button('edit')
click_link('.gitignore')
click_link_or_button('Edit')
expect(page).not_to have_link('Fork project')
find('#editor')
set_editor_value('*.rbca')
fill_in(:commit_message, with: 'Another commit', visible: true)
click_button('Commit changes')
fork = user.fork_of(project2)
expect(page).to have_current_path(project_new_merge_request_path(fork), ignore_query: true)
wait_for_requests
expect(page).to have_content('Another commit')
expect(page).to have_content("From #{forked_project.full_path}")
expect(page).to have_content("into #{project2.full_path}")
end
it_behaves_like 'unavailable for an archived project' do
let(:project) { project2 }
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Projects > Files > User replaces files', :js do
include DropzoneHelper
let(:fork_message) do
"You're not allowed to make changes to this project directly. "\
"A fork of this project has been created that you can make changes in, so you can submit a merge request."
end
let(:project) { create(:project, :repository, name: 'Shop') }
let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') }
let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) }
let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) }
let(:user) { create(:user) }
before do
stub_feature_flags(refactor_blob_viewer: false)
sign_in(user)
end
context 'when an user has write access' do
before do
project.add_maintainer(user)
visit(project_tree_path_root_ref)
wait_for_requests
end
it 'replaces an existed file with a new one' do
click_link('.gitignore')
expect(page).to have_content('.gitignore')
click_on('Replace')
drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'Replacement file commit message')
end
click_button('Replace file')
expect(page).to have_content('Lorem ipsum dolor sit amet')
expect(page).to have_content('Sed ut perspiciatis unde omnis')
expect(page).to have_content('Replacement file commit message')
end
end
context 'when an user does not have write access' do
before do
project2.add_reporter(user)
visit(project2_tree_path_root_ref)
wait_for_requests
end
it 'replaces an existed file with a new one in a forked project', :sidekiq_might_not_need_inline do
click_link('.gitignore')
expect(page).to have_content('.gitignore')
click_on('Replace')
expect(page).to have_link('Fork')
expect(page).to have_button('Cancel')
click_link('Fork')
expect(page).to have_content(fork_message)
click_on('Replace')
drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'Replacement file commit message')
end
click_button('Replace file')
expect(page).to have_content('Replacement file commit message')
fork = user.fork_of(project2.reload)
expect(page).to have_current_path(project_new_merge_request_path(fork), ignore_query: true)
click_link('Changes')
expect(page).to have_content('Lorem ipsum dolor sit amet')
expect(page).to have_content('Sed ut perspiciatis unde omnis')
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment