Commit 45a4ada4 authored by Markus Koller's avatar Markus Koller

Decouple wiki controller from projects

This is in preparation for group wikis.

- Extract wiki controller actions into a concern
- Use `container` instead of `@project`.
- Replace `@wiki` / `load_project_wiki` and `@page` / `load_page`
  with `wiki` and `page` getters.
- Add `load_sidebar`, and don't call it in the `pages` action.
- Add `wiki_page_path` routing helper.
- Use `wiki_page` factory in specs and remove manual page setup.
parent a27d63dc
......@@ -32,7 +32,7 @@ module PreviewMarkdown
def markdown_context_params
case controller_name
when 'wikis' then { pipeline: :wiki, wiki: @project_wiki, page_slug: params[:id] }
when 'wikis' then { pipeline: :wiki, wiki: wiki, page_slug: params[:id] }
when 'snippets' then { skip_project_check: true }
when 'groups' then { group: group }
when 'projects' then projects_filter_params
......
# frozen_string_literal: true
module WikiActions
include SendsBlob
include Gitlab::Utils::StrongMemoize
extend ActiveSupport::Concern
included do
before_action :authorize_read_wiki!
before_action :authorize_create_wiki!, only: [:edit, :create]
before_action :authorize_admin_wiki!, only: :destroy
before_action :wiki
before_action :page, only: [:show, :edit, :update, :history, :destroy]
before_action :load_sidebar, except: [:pages]
before_action only: [:show, :edit, :update] do
@valid_encoding = valid_encoding?
end
before_action only: [:edit, :update], unless: :valid_encoding? do
redirect_to wiki_page_path(wiki, page)
end
end
def new
redirect_to wiki_page_path(wiki, SecureRandom.uuid, random_title: true)
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def pages
@wiki_pages = Kaminari.paginate_array(
wiki.list_pages(sort: params[:sort], direction: params[:direction])
).page(params[:page])
@wiki_entries = WikiPage.group_by_directory(@wiki_pages)
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
# `#show` handles a number of scenarios:
#
# - If `id` matches a WikiPage, then show the wiki page.
# - If `id` is a file in the wiki repository, then send the file.
# - If we know the user wants to create a new page with the given `id`,
# then display a create form.
# - Otherwise show the empty wiki page and invite the user to create a page.
#
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def show
if page
set_encoding_error unless valid_encoding?
# Assign vars expected by MarkupHelper
@ref = params[:version_id]
@path = page.path
render 'show'
elsif file_blob
send_blob(wiki.repository, file_blob, allow_caching: container.public?)
elsif show_create_form?
# Assign a title to the WikiPage unless `id` is a randomly generated slug from #new
title = params[:id] unless params[:random_title].present?
@page = build_page(title: title)
render 'edit'
else
render 'empty'
end
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
def edit
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def update
return render('empty') unless can?(current_user, :create_wiki, container)
@page = WikiPages::UpdateService.new(container: container, current_user: current_user, params: wiki_params).execute(page)
if page.valid?
redirect_to(
wiki_page_path(wiki, page),
notice: _('Wiki was successfully updated.')
)
else
render 'edit'
end
rescue WikiPage::PageChangedError, WikiPage::PageRenameError, Gitlab::Git::Wiki::OperationError => e
@error = e
render 'edit'
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def create
@page = WikiPages::CreateService.new(container: container, current_user: current_user, params: wiki_params).execute
if page.persisted?
redirect_to(
wiki_page_path(wiki, page),
notice: _('Wiki was successfully updated.')
)
else
render action: "edit"
end
rescue Gitlab::Git::Wiki::OperationError => e
@page = build_page(wiki_params)
@error = e
render 'edit'
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def history
if page
@page_versions = Kaminari.paginate_array(page.versions(page: params[:page].to_i),
total_count: page.count_versions)
.page(params[:page])
else
redirect_to(
wiki_page_path(wiki, :home),
notice: _("Page not found")
)
end
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def destroy
WikiPages::DestroyService.new(container: container, current_user: current_user).execute(page)
redirect_to wiki_page_path(wiki, :home),
status: :found,
notice: _("Page was successfully deleted")
rescue Gitlab::Git::Wiki::OperationError => e
@error = e
render 'edit'
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
private
def container
raise NotImplementedError
end
def show_create_form?
can?(current_user, :create_wiki, container) &&
page.nil? &&
# Always show the create form when the wiki has had at least one page created.
# Otherwise, we only show the form when the user has navigated from
# the 'empty wiki' page
(wiki.exists? || params[:view] == 'create')
end
def wiki
strong_memoize(:wiki) do
wiki = Wiki.for_container(container, current_user)
# Call #wiki to make sure the Wiki Repo is initialized
wiki.wiki
wiki
end
rescue Wiki::CouldNotCreateWikiError
flash[:notice] = _("Could not create Wiki Repository at this time. Please try again later.")
redirect_to container
false
end
def page
strong_memoize(:page) do
wiki.find_page(*page_params)
end
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def load_sidebar
@sidebar_page = wiki.find_sidebar(params[:version_id])
unless @sidebar_page # Fallback to default sidebar
@sidebar_wiki_entries, @sidebar_limited = wiki.sidebar_entries
end
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
def wiki_params
params.require(:wiki).permit(:title, :content, :format, :message, :last_commit_sha)
end
def build_page(args = {})
WikiPage.new(wiki).tap do |page|
page.update_attributes(args) # rubocop:disable Rails/ActiveRecordAliases
end
end
def page_params
keys = [:id]
keys << :version_id if params[:action] == 'show'
params.values_at(*keys)
end
def valid_encoding?
page_encoding == Encoding::UTF_8
end
def page_encoding
strong_memoize(:page_encoding) { page&.content&.encoding }
end
def set_encoding_error
flash.now[:notice] = _("The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.")
end
def file_blob
strong_memoize(:file_blob) do
commit = wiki.repository.commit(wiki.default_branch)
next unless commit
wiki.repository.blob_at(commit.id, params[:id])
end
end
end
# frozen_string_literal: true
class Projects::WikisController < Projects::ApplicationController
include WikiActions
include PreviewMarkdown
include SendsBlob
include Gitlab::Utils::StrongMemoize
before_action :authorize_read_wiki!
before_action :authorize_create_wiki!, only: [:edit, :create]
before_action :authorize_admin_wiki!, only: :destroy
before_action :load_project_wiki
before_action :load_page, only: [:show, :edit, :update, :history, :destroy]
before_action only: [:show, :edit, :update] do
@valid_encoding = valid_encoding?
end
before_action only: [:edit, :update], unless: :valid_encoding? do
redirect_to(project_wiki_path(@project, @page))
end
def new
redirect_to project_wiki_path(@project, SecureRandom.uuid, random_title: true)
end
def pages
@wiki_pages = Kaminari.paginate_array(
@project_wiki.list_pages(sort: params[:sort], direction: params[:direction])
).page(params[:page])
@wiki_entries = WikiPage.group_by_directory(@wiki_pages)
end
# `#show` handles a number of scenarios:
#
# - If `id` matches a WikiPage, then show the wiki page.
# - If `id` is a file in the wiki repository, then send the file.
# - If we know the user wants to create a new page with the given `id`,
# then display a create form.
# - Otherwise show the empty wiki page and invite the user to create a page.
def show
if @page
set_encoding_error unless valid_encoding?
# Assign vars expected by MarkupHelper
@ref = params[:version_id]
@path = @page.path
render 'show'
elsif file_blob
send_blob(@project_wiki.repository, file_blob, allow_caching: @project.public?)
elsif show_create_form?
# Assign a title to the WikiPage unless `id` is a randomly generated slug from #new
title = params[:id] unless params[:random_title].present?
@page = build_page(title: title)
render 'edit'
else
render 'empty'
end
end
def edit
end
def update
return render('empty') unless can?(current_user, :create_wiki, @project)
@page = WikiPages::UpdateService.new(container: @project, current_user: current_user, params: wiki_params).execute(@page)
if @page.valid?
redirect_to(
project_wiki_path(@project, @page),
notice: _('Wiki was successfully updated.')
)
else
render 'edit'
end
rescue WikiPage::PageChangedError, WikiPage::PageRenameError, Gitlab::Git::Wiki::OperationError => e
@error = e
render 'edit'
end
def create
@page = WikiPages::CreateService.new(container: @project, current_user: current_user, params: wiki_params).execute
if @page.persisted?
redirect_to(
project_wiki_path(@project, @page),
notice: _('Wiki was successfully updated.')
)
else
render action: "edit"
end
rescue Gitlab::Git::Wiki::OperationError => e
@page = build_page(wiki_params)
@error = e
render 'edit'
end
def history
if @page
@page_versions = Kaminari.paginate_array(@page.versions(page: params[:page].to_i),
total_count: @page.count_versions)
.page(params[:page])
else
redirect_to(
project_wiki_path(@project, :home),
notice: _("Page not found")
)
end
end
def destroy
WikiPages::DestroyService.new(container: @project, current_user: current_user).execute(@page)
redirect_to project_wiki_path(@project, :home),
status: :found,
notice: _("Page was successfully deleted")
rescue Gitlab::Git::Wiki::OperationError => e
@error = e
render 'edit'
end
alias_method :container, :project
def git_access
end
private
def show_create_form?
can?(current_user, :create_wiki, @project) &&
@page.nil? &&
# Always show the create form when the wiki has had at least one page created.
# Otherwise, we only show the form when the user has navigated from
# the 'empty wiki' page
(@project_wiki.exists? || params[:view] == 'create')
end
def load_project_wiki
@project_wiki = load_wiki
# Call #wiki to make sure the Wiki Repo is initialized
@project_wiki.wiki
@sidebar_page = @project_wiki.find_sidebar(params[:version_id])
unless @sidebar_page # Fallback to default sidebar
@sidebar_wiki_entries, @sidebar_limited = @project_wiki.sidebar_entries
end
rescue ProjectWiki::CouldNotCreateWikiError
flash[:notice] = _("Could not create Wiki Repository at this time. Please try again later.")
redirect_to project_path(@project)
false
end
def load_wiki
ProjectWiki.new(@project, current_user)
end
def wiki_params
params.require(:wiki).permit(:title, :content, :format, :message, :last_commit_sha)
end
def build_page(args = {})
WikiPage.new(@project_wiki).tap do |page|
page.update_attributes(args) # rubocop:disable Rails/ActiveRecordAliases
end
end
def load_page
@page ||= find_page
end
def find_page
@project_wiki.find_page(*page_params)
end
def page_params
keys = [:id]
keys << :version_id if params[:action] == 'show'
params.values_at(*keys)
end
def valid_encoding?
page_encoding == Encoding::UTF_8
end
def page_encoding
strong_memoize(:page_encoding) { @page&.content&.encoding }
end
def set_encoding_error
flash.now[:notice] = _("The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.")
end
def file_blob
strong_memoize(:file_blob) do
commit = @project_wiki.repository.commit(@project_wiki.default_branch)
next unless commit
@project_wiki.repository.blob_at(commit.id, params[:id])
end
end
end
......@@ -310,8 +310,8 @@ class ProjectsController < Projects::ApplicationController
render 'projects/empty' if @project.empty_repo?
else
if can?(current_user, :read_wiki, @project)
@project_wiki = @project.wiki
@wiki_home = @project_wiki.find_page('home', params[:version_id])
@wiki = @project.wiki
@wiki_home = @wiki.find_page('home', params[:version_id])
elsif @project.feature_available?(:issues, current_user)
@issues = issuables_collection.page(params[:page])
@issuable_meta_data = Gitlab::IssuableMetadata.new(current_user, @issues).data
......
......@@ -298,6 +298,12 @@ module GitlabRoutingHelper
toggle_award_emoji_snippet_url(snippet, *new_args)
end
# Wikis
def wiki_page_path(wiki, page, **options)
Gitlab::UrlBuilder.wiki_page_url(wiki, page, **options, only_path: true)
end
private
def snippet_query_params(snippet, *args)
......
......@@ -129,8 +129,8 @@ module MarkupHelper
context.merge!(
pipeline: :wiki,
project: @project,
wiki: @project_wiki,
repository: @project_wiki.repository,
wiki: @wiki,
repository: @wiki.repository,
page_slug: wiki_page.slug,
issuable_state_filter_enabled: true
)
......@@ -300,7 +300,7 @@ module MarkupHelper
# RepositoryLinkFilter and UploadLinkFilter
commit: @commit,
project_wiki: @project_wiki,
wiki: @wiki,
ref: @ref,
requested_path: @path
)
......
......@@ -8,10 +8,10 @@
.git-access-header.w-100.d-flex.flex-column.justify-content-center
%span
= _("Clone repository")
%strong= @project_wiki.full_path
%strong= @wiki.full_path
.pt-3.pt-lg-0.w-100
= render "shared/clone_panel", project: @project_wiki
= render "shared/clone_panel", project: @wiki
.wiki-git-access
%h3= s_("WikiClone|Install Gollum")
......@@ -22,8 +22,8 @@
%h3= s_("WikiClone|Clone your wiki")
%pre.dark
:preserve
git clone #{ content_tag(:span, h(default_url_to_repo(@project_wiki)), class: 'clone')}
cd #{h @project_wiki.path}
git clone #{ content_tag(:span, h(default_url_to_repo(@wiki)), class: 'clone')}
cd #{h @wiki.path}
%h3= s_("WikiClone|Start Gollum and edit locally")
%pre.dark
......
......@@ -35,12 +35,12 @@ module EE
end
end
override :wiki_url
def wiki_url(object, **options)
if object.container.is_a?(Group)
override :wiki_page_url
def wiki_page_url(wiki, page, **options)
if wiki.container.is_a?(Group)
# TODO: Use the new route for group wikis once we add it.
# https://gitlab.com/gitlab-org/gitlab/-/issues/211360
instance.group_canonical_url(object.container, **options) + "/-/wikis/#{::Wiki::HOMEPAGE}"
instance.group_canonical_url(wiki.container, **options) + "/-/wikis/#{page.to_param}"
else
super
end
......
......@@ -39,9 +39,9 @@ module Gitlab
when User
instance.user_url(object, **options)
when Wiki
wiki_url(object, **options)
wiki_page_url(object, Wiki::HOMEPAGE, **options)
when WikiPage
instance.project_wiki_url(object.wiki.project, object.slug, **options)
wiki_page_url(object.wiki, object, **options)
when ::DesignManagement::Design
design_url(object, **options)
else
......@@ -78,11 +78,11 @@ module Gitlab
end
end
def wiki_url(object, **options)
if object.container.is_a?(Project)
instance.project_wiki_url(object.container, Wiki::HOMEPAGE, **options)
def wiki_page_url(wiki, page, **options)
if wiki.container.is_a?(Project)
instance.project_wiki_url(wiki.container, page, **options)
else
raise NotImplementedError.new("No URL builder defined for #{object.inspect}")
raise NotImplementedError.new("No URL builder defined for #{wiki.container.inspect} wikis")
end
end
......
......@@ -3,282 +3,8 @@
require 'spec_helper'
RSpec.describe Projects::WikisController do
let_it_be(:project) { create(:project, :public, :repository) }
let(:user) { project.owner }
let(:project_wiki) { ProjectWiki.new(project, user) }
let(:wiki) { project_wiki.wiki }
let(:wiki_title) { 'page title test' }
before do
create_page(wiki_title, 'hello world')
sign_in(user)
end
after do
destroy_page(wiki_title)
end
describe 'GET #new' do
subject { get :new, params: { namespace_id: project.namespace, project_id: project } }
it 'redirects to #show and appends a `random_title` param' do
subject
expect(response).to have_gitlab_http_status(:found)
expect(Rails.application.routes.recognize_path(response.redirect_url)).to include(
controller: 'projects/wikis',
action: 'show'
)
expect(response.redirect_url).to match(/\?random_title=true\Z/)
end
end
describe 'GET #pages' do
subject { get :pages, params: { namespace_id: project.namespace, project_id: project, id: wiki_title } }
it 'does not load the pages content' do
expect(controller).to receive(:load_wiki).and_return(project_wiki)
expect(project_wiki).to receive(:list_pages).twice.and_call_original
subject
end
end
describe 'GET #history' do
before do
allow(controller)
.to receive(:can?)
.with(any_args)
.and_call_original
# The :create_wiki permission is irrelevant to reading history.
expect(controller)
.not_to receive(:can?)
.with(anything, :create_wiki, any_args)
allow(controller)
.to receive(:can?)
.with(anything, :read_wiki, any_args)
.and_return(allow_read_wiki)
end
shared_examples 'fetching history' do |expected_status|
before do
get :history, params: { namespace_id: project.namespace, project_id: project, id: wiki_title }
end
it "returns status #{expected_status}" do
expect(response).to have_gitlab_http_status(expected_status)
end
end
it_behaves_like 'fetching history', :ok do
let(:allow_read_wiki) { true }
it 'assigns @page_versions' do
expect(assigns(:page_versions)).to be_present
end
end
it_behaves_like 'fetching history', :not_found do
let(:allow_read_wiki) { false }
end
end
describe 'GET #show' do
render_views
let(:random_title) { nil }
subject { get :show, params: { namespace_id: project.namespace, project_id: project, id: id, random_title: random_title } }
context 'when page exists' do
let(:id) { wiki_title }
it 'limits the retrieved pages for the sidebar' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:page).title).to eq(wiki_title)
expect(assigns(:sidebar_wiki_entries)).to contain_exactly(an_instance_of(WikiPage))
expect(assigns(:sidebar_limited)).to be(false)
end
context 'when page content encoding is invalid' do
it 'sets flash error' do
allow(controller).to receive(:valid_encoding?).and_return(false)
subject
expect(response).to have_gitlab_http_status(:ok)
expect(flash[:notice]).to eq(_('The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.'))
end
end
end
context 'when the page does not exist' do
let(:id) { 'does not exist' }
before do
subject
end
it 'builds a new wiki page with the id as the title' do
expect(assigns(:page).title).to eq(id)
end
context 'when a random_title param is present' do
let(:random_title) { true }
it 'builds a new wiki page with no title' do
expect(assigns(:page).title).to be_empty
end
end
end
context 'when page is a file' do
include WikiHelpers
let(:id) { upload_file_to_wiki(project, user, file_name) }
context 'when file is an image' do
let(:file_name) { 'dk.png' }
it 'delivers the image' do
subject
expect(response.headers['Content-Disposition']).to match(/^inline/)
expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
context 'when file is a svg' do
let(:file_name) { 'unsanitized.svg' }
it 'delivers the image' do
subject
expect(response.headers['Content-Disposition']).to match(/^inline/)
expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
end
it_behaves_like 'project cache control headers'
end
context 'when file is a pdf' do
let(:file_name) { 'git-cheat-sheet.pdf' }
it 'sets the content type to sets the content response headers' do
subject
expect(response.headers['Content-Disposition']).to match(/^inline/)
expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
it_behaves_like 'project cache control headers'
end
end
end
describe 'POST #preview_markdown' do
it 'renders json in a correct format' do
post :preview_markdown, params: { namespace_id: project.namespace, project_id: project, id: 'page/path', text: '*Markdown* text' }
expect(json_response.keys).to match_array(%w(body references))
end
end
describe 'GET #edit' do
subject { get(:edit, params: { namespace_id: project.namespace, project_id: project, id: wiki_title }) }
context 'when page content encoding is invalid' do
it 'redirects to show' do
allow(controller).to receive(:valid_encoding?).and_return(false)
subject
expect(response).to redirect_to_wiki(project, project_wiki.list_pages.first)
end
end
context 'when the page has nil content' do
let(:page) { create(:wiki_page) }
it 'redirects to show' do
allow(page).to receive(:content).and_return(nil)
allow(controller).to receive(:find_page).and_return(page)
subject
expect(response).to redirect_to_wiki(project, page)
end
end
context 'when page content encoding is valid' do
render_views
it 'shows the edit page' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(response.body).to include(s_('Wiki|Edit Page'))
end
end
end
describe 'PATCH #update' do
let(:new_title) { 'New title' }
let(:new_content) { 'New content' }
subject do
patch(:update,
params: {
namespace_id: project.namespace,
project_id: project,
id: wiki_title,
wiki: { title: new_title, content: new_content }
})
end
context 'when page content encoding is invalid' do
it 'redirects to show' do
allow(controller).to receive(:valid_encoding?).and_return(false)
subject
expect(response).to redirect_to_wiki(project, project_wiki.list_pages.first)
end
end
context 'when page content encoding is valid' do
render_views
it 'updates the page' do
subject
wiki_page = project_wiki.list_pages(load_content: true).first
expect(wiki_page.title).to eq new_title
expect(wiki_page.content).to eq new_content
end
end
end
def create_page(name, content)
wiki.write_page(name, :markdown, content, commit_details(name))
end
def commit_details(name)
Gitlab::Git::Wiki::CommitDetails.new(user.id, user.username, user.name, user.email, "created page #{name}")
end
def destroy_page(title, dir = '')
page = wiki.page(title: title, dir: dir)
project_wiki.delete_page(page, "test commit")
end
def redirect_to_wiki(project, page)
redirect_to(controller.project_wiki_path(project, page))
it_behaves_like 'wiki controller actions' do
let(:container) { create(:project, :public, :repository, namespace: user.namespace) }
let(:routing_params) { { namespace_id: container.namespace, project_id: container } }
end
end
......@@ -229,4 +229,14 @@ describe GitlabRoutingHelper do
end
end
end
context 'wikis' do
let(:wiki) { create(:project_wiki) }
describe '#wiki_page_path' do
it 'returns the url for the wiki page' do
expect(wiki_page_path(wiki, 'page')).to eq("/#{wiki.project.full_path}/-/wikis/page")
end
end
end
end
......@@ -327,7 +327,7 @@ describe MarkupHelper do
expect(wiki).to receive(:content).and_return('wiki content')
expect(wiki).to receive(:slug).and_return('nested/page')
expect(wiki).to receive(:repository).and_return(wiki_repository)
helper.instance_variable_set(:@project_wiki, wiki)
helper.instance_variable_set(:@wiki, wiki)
end
context 'when file is Markdown' do
......
......@@ -8,14 +8,14 @@ module WikiHelpers
find('.svg-content .js-lazy-loaded') if example.nil? || example.metadata.key?(:js)
end
def upload_file_to_wiki(project, user, file_name)
def upload_file_to_wiki(container, user, file_name)
opts = {
file_name: file_name,
file_content: File.read(expand_fixture_path(file_name))
}
::Wikis::CreateAttachmentService.new(
container: project,
container: container,
current_user: user,
params: opts
).execute[:result][:file_path]
......
# frozen_string_literal: true
RSpec.shared_examples 'wiki controller actions' do
let(:container) { raise NotImplementedError }
let(:routing_params) { raise NotImplementedError }
let_it_be(:user) { create(:user) }
let(:wiki) { Wiki.for_container(container, user) }
let(:wiki_title) { 'page title test' }
before do
create(:wiki_page, wiki: wiki, title: wiki_title, content: 'hello world')
sign_in(user)
end
describe 'GET #new' do
subject { get :new, params: routing_params }
it 'redirects to #show and appends a `random_title` param' do
subject
expect(response).to be_redirect
expect(response.redirect_url).to match(%r{
#{Regexp.quote(wiki.wiki_base_path)} # wiki base path
/[-\h]{36} # page slug
\?random_title=true\Z # random_title param
}x)
end
context 'when the wiki repository cannot be created' do
before do
expect(Wiki).to receive(:for_container).and_return(wiki)
expect(wiki).to receive(:wiki) { raise Wiki::CouldNotCreateWikiError }
end
it 'redirects to the wiki container and displays an error message' do
subject
expect(response).to redirect_to(container)
expect(flash[:notice]).to eq('Could not create Wiki Repository at this time. Please try again later.')
end
end
end
describe 'GET #pages' do
before do
get :pages, params: routing_params.merge(id: wiki_title)
end
it 'assigns the page collections' do
expect(assigns(:wiki_pages)).to contain_exactly(an_instance_of(WikiPage))
expect(assigns(:wiki_entries)).to contain_exactly(an_instance_of(WikiPage))
end
it 'does not load the page content' do
expect(assigns(:page)).to be_nil
end
it 'does not load the sidebar' do
expect(assigns(:sidebar_wiki_entries)).to be_nil
expect(assigns(:sidebar_limited)).to be_nil
end
end
describe 'GET #history' do
before do
allow(controller)
.to receive(:can?)
.with(any_args)
.and_call_original
# The :create_wiki permission is irrelevant to reading history.
expect(controller)
.not_to receive(:can?)
.with(anything, :create_wiki, any_args)
allow(controller)
.to receive(:can?)
.with(anything, :read_wiki, any_args)
.and_return(allow_read_wiki)
end
shared_examples 'fetching history' do |expected_status|
before do
get :history, params: routing_params.merge(id: wiki_title)
end
it "returns status #{expected_status}" do
expect(response).to have_gitlab_http_status(expected_status)
end
end
it_behaves_like 'fetching history', :ok do
let(:allow_read_wiki) { true }
it 'assigns @page_versions' do
expect(assigns(:page_versions)).to be_present
end
end
it_behaves_like 'fetching history', :not_found do
let(:allow_read_wiki) { false }
end
end
describe 'GET #show' do
render_views
let(:random_title) { nil }
subject { get :show, params: routing_params.merge(id: id, random_title: random_title) }
context 'when page exists' do
let(:id) { wiki_title }
it 'renders the page' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:page).title).to eq(wiki_title)
expect(assigns(:sidebar_wiki_entries)).to contain_exactly(an_instance_of(WikiPage))
expect(assigns(:sidebar_limited)).to be(false)
end
context 'when page content encoding is invalid' do
it 'sets flash error' do
allow(controller).to receive(:valid_encoding?).and_return(false)
subject
expect(response).to have_gitlab_http_status(:ok)
expect(flash[:notice]).to eq(_('The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.'))
end
end
end
context 'when the page does not exist' do
let(:id) { 'does not exist' }
before do
subject
end
it 'builds a new wiki page with the id as the title' do
expect(assigns(:page).title).to eq(id)
end
context 'when a random_title param is present' do
let(:random_title) { true }
it 'builds a new wiki page with no title' do
expect(assigns(:page).title).to be_empty
end
end
end
context 'when page is a file' do
include WikiHelpers
let(:id) { upload_file_to_wiki(container, user, file_name) }
context 'when file is an image' do
let(:file_name) { 'dk.png' }
it 'delivers the image' do
subject
expect(response.headers['Content-Disposition']).to match(/^inline/)
expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
context 'when file is a svg' do
let(:file_name) { 'unsanitized.svg' }
it 'delivers the image' do
subject
expect(response.headers['Content-Disposition']).to match(/^inline/)
expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
end
it_behaves_like 'project cache control headers' do
let(:project) { container }
end
end
context 'when file is a pdf' do
let(:file_name) { 'git-cheat-sheet.pdf' }
it 'sets the content type to sets the content response headers' do
subject
expect(response.headers['Content-Disposition']).to match(/^inline/)
expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
end
it_behaves_like 'project cache control headers' do
let(:project) { container }
end
end
end
end
describe 'POST #preview_markdown' do
it 'renders json in a correct format' do
post :preview_markdown, params: routing_params.merge(id: 'page/path', text: '*Markdown* text')
expect(json_response.keys).to match_array(%w(body references))
end
end
describe 'GET #edit' do
subject { get(:edit, params: routing_params.merge(id: wiki_title)) }
context 'when page content encoding is invalid' do
it 'redirects to show' do
allow(controller).to receive(:valid_encoding?).and_return(false)
subject
expect(response).to redirect_to_wiki(wiki, wiki.list_pages.first)
end
end
context 'when the page has nil content' do
let(:page) { create(:wiki_page) }
it 'redirects to show' do
allow(page).to receive(:content).and_return(nil)
allow(controller).to receive(:page).and_return(page)
subject
expect(response).to redirect_to_wiki(wiki, page)
end
end
context 'when page content encoding is valid' do
render_views
it 'shows the edit page' do
subject
expect(response).to have_gitlab_http_status(:ok)
expect(response.body).to include(s_('Wiki|Edit Page'))
end
end
end
describe 'PATCH #update' do
let(:new_title) { 'New title' }
let(:new_content) { 'New content' }
subject do
patch(:update,
params: routing_params.merge(
id: wiki_title,
wiki: { title: new_title, content: new_content }
))
end
context 'when page content encoding is invalid' do
it 'redirects to show' do
allow(controller).to receive(:valid_encoding?).and_return(false)
subject
expect(response).to redirect_to_wiki(wiki, wiki.list_pages.first)
end
end
context 'when page content encoding is valid' do
render_views
it 'updates the page' do
subject
wiki_page = wiki.list_pages(load_content: true).first
expect(wiki_page.title).to eq new_title
expect(wiki_page.content).to eq new_content
end
end
end
def redirect_to_wiki(wiki, page)
redirect_to(controller.wiki_page_path(wiki, page))
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