Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-10-23 06:06:01 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2019-10-23 06:06:01 +0300
commit8c7eab92cd0009f55cb999bbade43e0f969c137e (patch)
tree180cac6632448a211ddbe555191574c98e8dc385 /spec
parentdffeff5520e861dc6e7319b690c573186bbbd22e (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/wiki_directories_controller_spec.rb52
-rw-r--r--spec/controllers/projects/wiki_pages_controller_spec.rb399
-rw-r--r--spec/controllers/projects/wikis_controller_spec.rb239
-rw-r--r--spec/factories/wiki_pages.rb8
-rw-r--r--spec/features/projects/features_visibility_spec.rb102
-rw-r--r--spec/features/projects/wiki/markdown_preview_spec.rb170
-rw-r--r--spec/features/projects/wiki/user_creates_wiki_page_spec.rb219
-rw-r--r--spec/features/projects/wiki/user_deletes_wiki_page_spec.rb2
-rw-r--r--spec/features/projects/wiki/user_updates_wiki_page_spec.rb77
-rw-r--r--spec/features/projects/wiki/user_views_wiki_page_spec.rb31
-rw-r--r--spec/features/projects/wiki/user_views_wiki_pages_spec.rb172
-rw-r--r--spec/frontend/wikis_spec.js40
-rw-r--r--spec/helpers/wiki_helper_spec.rb21
-rw-r--r--spec/lib/banzai/filter/wiki_link_filter_spec.rb13
-rw-r--r--spec/lib/banzai/pipeline/wiki_pipeline_spec.rb209
-rw-r--r--spec/lib/gitlab/url_builder_spec.rb2
-rw-r--r--spec/lib/gitlab/utils_spec.rb37
-rw-r--r--spec/models/project_wiki_spec.rb22
-rw-r--r--spec/models/wiki_directory_spec.rb187
-rw-r--r--spec/models/wiki_page_spec.rb91
-rw-r--r--spec/routing/project_routing_spec.rb42
-rw-r--r--spec/routing/wiki_routing_spec.rb103
-rw-r--r--spec/support/controllers/authorization_helpers.rb6
-rw-r--r--spec/support/helpers/capybara_helpers.rb10
-rw-r--r--spec/support/helpers/dropzone_helper.rb2
-rw-r--r--spec/support/helpers/git_helpers.rb5
-rw-r--r--spec/support/helpers/wiki_helpers.rb6
-rw-r--r--spec/support/matchers/issuable_matchers.rb3
-rw-r--r--spec/support/shared_examples/wiki_file_attachments_examples.rb8
29 files changed, 1454 insertions, 824 deletions
diff --git a/spec/controllers/projects/wiki_directories_controller_spec.rb b/spec/controllers/projects/wiki_directories_controller_spec.rb
new file mode 100644
index 00000000000..b09e1bc2ca4
--- /dev/null
+++ b/spec/controllers/projects/wiki_directories_controller_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::WikiDirectoriesController do
+ set(:project) { create(:project, :public, :repository) }
+
+ let(:user) { project.owner }
+ let(:project_wiki) { ProjectWiki.new(project, user) }
+ let(:wiki) { project_wiki.wiki }
+ let(:dir_slug) { 'the-directory' }
+ let(:dir_contents) { [create(:wiki_page)] }
+ let(:the_dir) { WikiDirectory.new(dir_slug, dir_contents) }
+
+ before do
+ allow(controller).to receive(:find_dir).and_return(the_dir)
+
+ sign_in(user)
+ end
+
+ describe 'GET #show' do
+ let(:show_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: dir_slug
+ }
+ end
+
+ before do
+ get :show, params: show_params
+ end
+
+ context 'the directory is empty' do
+ let(:the_dir) { nil }
+
+ it { is_expected.to render_template('empty') }
+ end
+
+ context 'the directory does exist' do
+ it { is_expected.to render_template('show') }
+
+ it 'sets the wiki_dir attribute' do
+ expect(assigns(:wiki_dir)).to eq(the_dir)
+ end
+
+ it 'assigns the wiki pages' do
+ expect(assigns(:wiki_pages)).to eq(dir_contents)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects/wiki_pages_controller_spec.rb b/spec/controllers/projects/wiki_pages_controller_spec.rb
new file mode 100644
index 00000000000..01a84fbbf20
--- /dev/null
+++ b/spec/controllers/projects/wiki_pages_controller_spec.rb
@@ -0,0 +1,399 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::WikiPagesController do
+ set(: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' }
+ let(:parent_ids) { { namespace_id: project.namespace.path, project_id: project.name } }
+ let(:redirect_destination) { Rails.application.routes.recognize_path(response.redirect_url) }
+
+ before do
+ create_page(wiki_title, 'hello world')
+
+ sign_in(user)
+ end
+
+ after do
+ destroy_page(wiki_title)
+ end
+
+ def helper
+ Helper.instance
+ end
+
+ class Helper
+ include Singleton
+ include ActionView::Helpers::UrlHelper
+ end
+
+ describe 'GET #new' do
+ subject { get :new, params: parent_ids }
+
+ it 'redirects to #show and appends a `random_title` param' do
+ subject
+
+ expect(response).to have_http_status(302)
+
+ expect(redirect_destination)
+ .to include(parent_ids.merge(controller: 'projects/wiki_pages', action: 'show'))
+
+ expect(response.redirect_url).to match(/\?random_title=true\Z/)
+ end
+ end
+
+ describe 'GET #show' do
+ render_views
+ let(:requested_wiki_page) { wiki_title }
+ let(:random_title) { nil }
+
+ subject do
+ get :show, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: requested_wiki_page,
+ random_title: random_title
+ }
+ end
+
+ context 'when the wiki repo cannot be created' do
+ before do
+ allow(controller).to receive(:load_wiki) { raise ProjectWiki::CouldNotCreateWikiError }
+ end
+
+ it 'redirects to the project path' do
+ headers = { 'Location' => a_string_ending_with(Gitlab::Routing.url_helpers.project_path(project)) }
+
+ subject
+
+ expect(response).to be_redirect
+ expect(response.header.to_hash).to include(headers)
+ end
+ end
+
+ context 'when the page exists' do
+ it 'limits the retrieved pages for the sidebar' do
+ expect(controller).to receive(:load_wiki).and_return(project_wiki)
+
+ # Sidebar entries
+ expect(project_wiki).to receive(:list_pages).with(limit: 15).and_call_original
+
+ subject
+
+ expect(response).to have_http_status(:ok)
+ expect(response.body).to include(wiki_title)
+ 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_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(:requested_wiki_page) { 'this-page-does-not-yet-exist' }
+
+ context 'the current user can create wiki pages' do
+ it { is_expected.to render_template('edit') }
+
+ it 'makes a call to see if the wiki is empty' do
+ expect(controller).to receive(:load_wiki).and_return(project_wiki)
+ expect(project_wiki).to receive(:list_pages).once.with(limit: anything).and_call_original
+ expect(project_wiki).to receive(:list_pages).with(limit: 1).and_call_original
+ subject
+ end
+
+ describe 'assigned title' do
+ shared_examples :wiki_page_with_correct_title do
+ it 'assigns the correct title' do
+ subject
+
+ expect(assigns(:page)).to have_attributes(title: assigned_title)
+ end
+ end
+
+ context 'random_title is absent' do
+ let(:random_title) { nil }
+
+ it_behaves_like :wiki_page_with_correct_title do
+ let(:assigned_title) { WikiPage.unhyphenize(requested_wiki_page) }
+ end
+ end
+
+ context 'random_title is present' do
+ let(:random_title) { true }
+
+ it_behaves_like :wiki_page_with_correct_title do
+ let(:assigned_title) { be_empty }
+ end
+ end
+ end
+ end
+
+ context 'the current user cannot create wiki pages' do
+ before do
+ forbid_controller_ability! :create_wiki
+ end
+ it { is_expected.to render_template('missing_page') }
+ end
+ end
+
+ context 'when page is a file' do
+ include WikiHelpers
+
+ let(:path) { upload_file_to_wiki(project, user, file_name) }
+
+ before do
+ get :show, params: { namespace_id: project.namespace, project_id: project, id: path }
+ end
+
+ context 'when file is an image' do
+ let(:file_name) { 'dk.png' }
+
+ it 'delivers the image' do
+ 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
+ expect(response.headers['Content-Disposition']).to match(/^inline/)
+ expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
+ end
+ 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
+ expect(response.headers['Content-Disposition']).to match(/^inline/)
+ expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
+ end
+ end
+ end
+ end
+
+ describe 'POST #preview_markdown' do
+ let(:page_id) { 'page/path' }
+ let(:markdown_text) { '*Markdown* text' }
+ let(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: wiki_title }) }
+ let(:processed_md) { json_response.fetch('body') }
+
+ let(:preview_params) do
+ { namespace_id: project.namespace, project_id: project, id: wiki_page.slug, text: markdown_text }
+ end
+
+ before do
+ post :preview_markdown, params: preview_params
+ end
+
+ it 'renders json in a correct format' do
+ expect(response).to have_http_status(:ok)
+ expect(json_response).to include('body' => String, 'references' => Hash)
+ end
+
+ describe 'double brackets within backticks' do
+ let(:markdown_text) do
+ <<-HEREDOC
+ `[[do_not_linkify]]`
+ ```
+ [[also_do_not_linkify]]
+ ```
+ HEREDOC
+ end
+
+ it "does not linkify double brackets inside code blocks as expected" do
+ expect(processed_md).to include('[[do_not_linkify]]', '[[also_do_not_linkify]]')
+ end
+ end
+
+ describe 'link re-writing' do
+ let(:links) do
+ [
+ { text: 'regular link', path: 'regular' },
+ { text: 'relative link 1', path: '../relative' },
+ { text: 'relative link 2', path: './relative' },
+ { text: 'relative link 3', path: './e/f/relative' },
+ { text: 'spaced link', path: 'title with spaces' }
+ ]
+ end
+
+ shared_examples :wiki_link_rewriter do
+ let(:markdown_text) { links.map { |text:, path:| "[#{text}](#{path})" }.join("\n") }
+ let(:expected_links) do
+ links.zip(paths).map do |(link, path)|
+ helper.link_to(link[:text], "#{project_wiki.wiki_page_path}/#{path}")
+ end
+ end
+
+ it 'processes the links correctly' do
+ expect(processed_md).to include(*expected_links)
+ end
+ end
+
+ context 'the current page has spaces in its title' do
+ let(:wiki_title) { 'page a/page b/page c/page d' }
+ it_behaves_like :wiki_link_rewriter do
+ let(:paths) do
+ ['regular',
+ 'page-a/page-b/relative',
+ 'page-a/page-b/page-c/relative',
+ 'page-a/page-b/page-c/e/f/relative',
+ 'title%20with%20spaces']
+ end
+ end
+ end
+
+ context 'the current page has an unproblematic title' do
+ let(:wiki_title) { 'a/b/c/d' }
+ it_behaves_like :wiki_link_rewriter do
+ let(:paths) do
+ ['regular', 'a/b/relative', 'a/b/c/relative', 'a/b/c/e/f/relative', 'title%20with%20spaces']
+ end
+ end
+ end
+
+ context "when there are hyphens in the page name" do
+ let(:wiki_title) { 'page-a/page-b/page-c/page-d' }
+ it_behaves_like :wiki_link_rewriter do
+ let(:paths) do
+ ['regular',
+ 'page-a/page-b/relative',
+ 'page-a/page-b/page-c/relative',
+ 'page-a/page-b/page-c/e/f/relative',
+ 'title%20with%20spaces']
+ end
+ end
+ end
+ 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(project_wiki_path(project, project_wiki.list_pages.first))
+ end
+ end
+
+ context 'when page content encoding is valid' do
+ render_views
+
+ it 'shows the edit page' do
+ subject
+
+ expect(response).to have_http_status(:ok)
+ expect(response.body).to include('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_page: { 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(project_wiki_path(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
+
+ 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_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
+
+ private
+
+ 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
+end
diff --git a/spec/controllers/projects/wikis_controller_spec.rb b/spec/controllers/projects/wikis_controller_spec.rb
index f46da908218..7fbefa5787b 100644
--- a/spec/controllers/projects/wikis_controller_spec.rb
+++ b/spec/controllers/projects/wikis_controller_spec.rb
@@ -4,10 +4,10 @@ require 'spec_helper'
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' }
+ let_it_be(:user) { project.owner }
+ let_it_be(:project_wiki) { ProjectWiki.new(project, user) }
+ let_it_be(:wiki) { project_wiki.wiki }
+ let_it_be(:wiki_title) { 'page title test' }
before do
create_page(wiki_title, 'hello world')
@@ -19,231 +19,86 @@ describe Projects::WikisController 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_http_status(302)
- 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/)
+ describe 'GET #pages' do
+ subject do
+ get :pages, params: { namespace_id: project.namespace, project_id: project, id: wiki_title }.merge(extra_params)
end
- end
- describe 'GET #pages' do
- subject { get :pages, params: { namespace_id: project.namespace, project_id: project, id: wiki_title } }
+ let(:extra_params) { {} }
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_http_status(expected_status)
+ describe 'illegal params' do
+ shared_examples :a_bad_request do
+ it do
+ expect { subject }.to raise_error(ActionController::BadRequest)
+ end
end
- end
- it_behaves_like 'fetching history', :ok do
- let(:allow_read_wiki) { true }
+ describe ':sort' do
+ let(:extra_params) { { sort: 'wibble' } }
- it 'assigns @page_versions' do
- expect(assigns(:page_versions)).to be_present
+ it_behaves_like :a_bad_request
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 }
+ describe ':direction' do
+ let(:extra_params) { { direction: 'wibble' } }
- it 'limits the retrieved pages for the sidebar' do
- expect(controller).to receive(:load_wiki).and_return(project_wiki)
- expect(project_wiki).to receive(:list_pages).with(limit: 15).and_call_original
-
- subject
-
- expect(response).to have_http_status(:ok)
- expect(assigns(:page).title).to eq(wiki_title)
+ it_behaves_like :a_bad_request
end
- context 'when page content encoding is invalid' do
- it 'sets flash error' do
- allow(controller).to receive(:valid_encoding?).and_return(false)
-
- subject
+ describe ':show_children' do
+ let(:extra_params) { { show_children: 'wibble' } }
- expect(response).to have_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
+ it_behaves_like :a_bad_request
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
+ shared_examples 'sorting-and-nesting' do |sort_key, default_nesting|
+ context "the user is sorting by #{sort_key}" do
+ let(:extra_params) { sort_params.merge(nesting_params) }
+ let(:sort_params) { { sort: sort_key } }
+ let(:nesting_params) { {} }
- 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
+ before do
+ subject
end
- end
- end
- context 'when page is a file' do
- include WikiHelpers
-
- let(:id) { upload_file_to_wiki(project, user, file_name) }
-
- before do
- subject
- end
-
- context 'when file is an image' do
- let(:file_name) { 'dk.png' }
+ it "sets nesting to #{default_nesting} by default" do
+ expect(assigns :nesting).to eq default_nesting
+ end
- it 'delivers the image' do
- expect(response.headers['Content-Disposition']).to match(/^inline/)
- expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
+ it 'hides children if the default requires it' do
+ expect(assigns :show_children).to be(default_nesting != ProjectWiki::NESTING_CLOSED)
end
- context 'when file is a svg' do
- let(:file_name) { 'unsanitized.svg' }
+ ProjectWiki::NESTINGS.each do |nesting|
+ context "the user explicitly passes show_children = #{nesting}" do
+ let(:nesting_params) { { show_children: nesting } }
- it 'delivers the image' do
- expect(response.headers['Content-Disposition']).to match(/^inline/)
- expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
+ it 'sets nesting to the provided value' do
+ expect(assigns :nesting).to eq nesting
+ end
end
end
- end
- context 'when file is a pdf' do
- let(:file_name) { 'git-cheat-sheet.pdf' }
+ context 'the user wants children hidden' do
+ let(:nesting_params) { { show_children: 'hidden' } }
- it 'sets the content type to sets the content response headers' do
- expect(response.headers['Content-Disposition']).to match(/^inline/)
- expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq "true"
+ it 'hides children' do
+ expect(assigns :show_children).to be false
+ end
end
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(project_wiki_path(project, project_wiki.list_pages.first))
- end
- end
- context 'when page content encoding is valid' do
- render_views
-
- it 'shows the edit page' do
- subject
-
- expect(response).to have_http_status(:ok)
- expect(response.body).to include('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(project_wiki_path(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
+ include_examples 'sorting-and-nesting', ProjectWiki::CREATED_AT_ORDER, ProjectWiki::NESTING_FLAT
+ include_examples 'sorting-and-nesting', ProjectWiki::TITLE_ORDER, ProjectWiki::NESTING_CLOSED
end
def create_page(name, content)
diff --git a/spec/factories/wiki_pages.rb b/spec/factories/wiki_pages.rb
index 761ba58edb2..3ac8fe4ae43 100644
--- a/spec/factories/wiki_pages.rb
+++ b/spec/factories/wiki_pages.rb
@@ -18,12 +18,12 @@ FactoryBot.define do
association :wiki, factory: :project_wiki, strategy: :build
initialize_with { new(wiki, page, true) }
- before(:create) do |page, evaluator|
- page.attributes = evaluator.attrs
+ before(:create) do |wiki_page, evaluator|
+ wiki_page.attributes = evaluator.attrs.with_indifferent_access
end
- to_create do |page|
- page.create
+ to_create do |wiki_page|
+ wiki_page.create
end
end
end
diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb
index 9ec61743a11..8b7fef84dd7 100644
--- a/spec/features/projects/features_visibility_spec.rb
+++ b/spec/features/projects/features_visibility_spec.rb
@@ -3,8 +3,9 @@
require 'spec_helper'
describe 'Edit Project Settings' do
+ set(:project) { create(:project, :public, :repository) }
+
let(:member) { create(:user) }
- let!(:project) { create(:project, :public, :repository) }
let!(:issue) { create(:issue, project: project) }
let(:non_member) { create(:user) }
@@ -81,85 +82,88 @@ describe 'Edit Project Settings' do
end
describe 'project features visibility pages' do
- let(:pipeline) { create(:ci_empty_pipeline, project: project) }
- let(:job) { create(:ci_build, pipeline: pipeline) }
-
- let(:tools) do
- {
- builds: project_job_path(project, job),
- issues: project_issues_path(project),
- wiki: project_wiki_path(project, :home),
- snippets: project_snippets_path(project),
- merge_requests: project_merge_requests_path(project)
- }
+ set(:pipeline) { create(:ci_empty_pipeline, project: project) }
+ set(:job) { create(:ci_build, pipeline: pipeline) }
+
+ where(:method_name, :build_url) do
+ [
+ [:builds, -> { project_job_path(project, job) }],
+ [:issues, -> { project_issues_path(project) }],
+ [:wiki, -> { project_wiki_path(project, :home) }],
+ [:snippets, -> { project_snippets_path(project) }],
+ [:merge_requests, -> { project_merge_requests_path(project) }]
+ ]
end
- context 'normal user' do
- before do
- sign_in(member)
- end
+ with_them do
+ let(:url) { build_url.call }
+ let(:attr_name) { "#{method_name}_access_level" }
+
+ context 'normal user' do
+ before do
+ project.team.truncate
+ sign_in(member)
+ end
+
+ it 'renders 200 if tool is enabled' do
+ project.project_feature.update_attribute(attr_name, ProjectFeature::ENABLED)
- it 'renders 200 if tool is enabled' do
- tools.each do |method_name, url|
- project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::ENABLED)
visit url
+
expect(page.status_code).to eq(200)
end
- end
- it 'renders 404 if feature is disabled' do
- tools.each do |method_name, url|
- project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::DISABLED)
+ it 'renders 404 if feature is disabled' do
+ project.project_feature.update_attribute(attr_name, ProjectFeature::DISABLED)
+
visit url
+
expect(page.status_code).to eq(404)
end
- end
- it 'renders 404 if feature is enabled only for team members' do
- project.team.truncate
+ it 'renders 404 if feature is enabled only for team members' do
+ project.project_feature.update_attribute(attr_name, ProjectFeature::PRIVATE)
- tools.each do |method_name, url|
- project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::PRIVATE)
visit url
+
expect(page.status_code).to eq(404)
end
- end
- it 'renders 200 if user is member of group' do
- group = create(:group)
- project.group = group
- project.save
+ it 'renders 200 if user is member of group' do
+ group = create(:group)
+ project.group = group
+ project.save
- group.add_owner(member)
+ group.add_owner(member)
+
+ project.project_feature.update_attribute(attr_name, ProjectFeature::PRIVATE)
- tools.each do |method_name, url|
- project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::PRIVATE)
visit url
+
expect(page.status_code).to eq(200)
end
end
- end
- context 'admin user' do
- before do
- non_member.update_attribute(:admin, true)
- sign_in(non_member)
- end
+ context 'admin user' do
+ before do
+ non_member.update_attribute(:admin, true)
+ project.team.truncate
+ sign_in(non_member)
+ end
- it 'renders 404 if feature is disabled' do
- tools.each do |method_name, url|
+ it 'renders 404 if feature is disabled' do
project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::DISABLED)
+
visit url
+
expect(page.status_code).to eq(404)
end
- end
- it 'renders 200 if feature is enabled only for team members' do
- project.team.truncate
-
- tools.each do |method_name, url|
+ it 'renders 200 if feature is enabled only for team members' do
project.project_feature.update_attribute("#{method_name}_access_level", ProjectFeature::PRIVATE)
+
visit url
+
expect(page.status_code).to eq(200)
end
end
diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb
index 5c6b04a7141..a56b3e4955a 100644
--- a/spec/features/projects/wiki/markdown_preview_spec.rb
+++ b/spec/features/projects/wiki/markdown_preview_spec.rb
@@ -4,164 +4,54 @@ require 'spec_helper'
describe 'Projects > Wiki > User previews markdown changes', :js do
set(:user) { create(:user) }
- let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
- let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: '[some link](other-page)' }) }
- let(:wiki_content) do
- <<-HEREDOC
-[regular link](regular)
-[relative link 1](../relative)
-[relative link 2](./relative)
-[relative link 3](./e/f/relative)
-[spaced link](title with spaces)
- HEREDOC
- end
+ set(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
+ let(:project_wiki) { ProjectWiki.new(project, user) }
before do
project.add_maintainer(user)
-
sign_in(user)
+ init_home!
end
- context "while creating a new wiki page" do
- context "when there are no spaces or hyphens in the page name" do
- it "rewrites relative links as expected" do
- create_wiki_page('a/b/c/d', content: wiki_content)
-
- expect(page).to have_content("regular link")
-
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/relative\">relative link 1</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/relative\">relative link 2</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/e/f/relative\">relative link 3</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>")
- end
- end
-
- context "when there are spaces in the page name" do
- it "rewrites relative links as expected" do
- create_wiki_page('a page/b page/c page/d page', content: wiki_content)
-
- expect(page).to have_content("regular link")
-
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>")
- end
- end
-
- context "when there are hyphens in the page name" do
- it "rewrites relative links as expected" do
- create_wiki_page('a-page/b-page/c-page/d-page', content: wiki_content)
-
- expect(page).to have_content("regular link")
-
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>")
- end
- end
+ def init_home!
+ create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: '[some link](other-page)' })
end
- context "while editing a wiki page" do
- context "when there are no spaces or hyphens in the page name" do
- it "rewrites relative links as expected" do
- create_wiki_page('a/b/c/d')
- click_link 'Edit'
-
- fill_in :wiki_content, with: wiki_content
- click_on "Preview"
-
- expect(page).to have_content("regular link")
-
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/relative\">relative link 1</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/relative\">relative link 2</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a/b/c/e/f/relative\">relative link 3</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>")
- end
- end
-
- context "when there are spaces in the page name" do
- it "rewrites relative links as expected" do
- create_wiki_page('a page/b page/c page/d page')
- click_link 'Edit'
-
- fill_in :wiki_content, with: wiki_content
- click_on "Preview"
-
- expect(page).to have_content("regular link")
-
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>")
- end
- end
-
- context "when there are hyphens in the page name" do
- it "rewrites relative links as expected" do
- create_wiki_page('a-page/b-page/c-page/d-page')
- click_link 'Edit'
-
- fill_in :wiki_content, with: wiki_content
- click_on "Preview"
-
- expect(page).to have_content("regular link")
-
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/regular\">regular link</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/relative\">relative link 1</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>")
- expect(page.html).to include("<a href=\"/#{project.full_path}/wikis/title%20with%20spaces\">spaced link</a>")
- end
+ def fill_in_content!
+ page.within '.wiki-form' do
+ fill_in :wiki_page_content, with: wiki_content
end
+ end
- context 'when rendering the preview' do
- it 'renders content with CommonMark' do
- create_wiki_page('a-page/b-page/c-page/common-mark')
- click_link 'Edit'
-
- fill_in :wiki_content, with: "1. one\n - sublist\n"
- click_on "Preview"
-
- # 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
+ def show_preview!
+ page.within '.wiki-form' do
+ click_on 'Preview'
end
end
- it "does not linkify double brackets inside code blocks as expected" do
- wiki_content = <<-HEREDOC
- `[[do_not_linkify]]`
- ```
- [[also_do_not_linkify]]
- ```
- HEREDOC
-
- create_wiki_page('linkify_test', wiki_content)
+ context 'when writing a new page' do
+ let(:new_wiki_path) { 'a/b/c/d' }
+ let(:wiki_content) { 'Some [awesome wiki](content)' }
- expect(page).to have_content("do_not_linkify")
+ it 'can show a preview of markdown content' do
+ visit project_wiki_pages_new_path(project, id: new_wiki_path)
+ fill_in_content!
+ show_preview!
- expect(page.html).to include('[[do_not_linkify]]')
- expect(page.html).to include('[[also_do_not_linkify]]')
+ expect(page).to have_link('awesome wiki')
+ end
end
- private
-
- def create_wiki_page(path, content = 'content')
- visit project_wiki_path(project, wiki_page)
+ context 'when editing an existing page' do
+ let(:wiki_content) { 'Some [bemusing](content)' }
+ let(:wiki_page) { create(:wiki_page, wiki: project_wiki) }
- click_link 'New page'
+ it 'can show a preview of markdown content, when writing' do
+ visit project_wiki_edit_path(project, wiki_page)
+ fill_in_content!
+ show_preview!
- fill_in :wiki_title, with: path
- fill_in :wiki_content, with: content
-
- click_button 'Create page'
+ expect(page).to have_link('bemusing')
+ end
end
end
diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
index 56d0518015d..6b651ccb67a 100644
--- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
@@ -3,9 +3,15 @@
require "spec_helper"
describe "User creates wiki page" do
- let(:user) { create(:user) }
- let(:wiki) { ProjectWiki.new(project, user) }
+ include CapybaraHelpers
+ include WikiHelpers
+
+ set(:user) { create(:user) }
+
let(:project) { create(:project) }
+ let(:wiki) { ProjectWiki.new(project, user) }
+ let(:new_page) { WikiPage.new(wiki) }
+ let(:message_field) { form_field_name(new_page, :message) }
before do
project.add_maintainer(user)
@@ -13,38 +19,78 @@ describe "User creates wiki page" do
sign_in(user)
end
+ def start_writing(page_path)
+ click_link("New page")
+ fill_in(:wiki_page_title, with: page_path)
+ end
+
+ def create_page(attrs = {})
+ page.within(".wiki-form") do
+ attrs.each do |k, v|
+ fill_in("wiki_page_#{k}".to_sym, with: v)
+ end
+ end
+ click_on("Create page")
+ end
+
+ shared_examples 'updates commit message' do
+ describe 'commit message', :js do
+ it "has `Create home` as a commit message" do
+ wait_for_requests
+
+ expect(page).to have_field(message_field, with: "Create home")
+ end
+ end
+ end
+
context "when wiki is empty" do
before do
visit(project_wikis_path(project))
click_link "Create your first page"
+ find('.wiki-form')
end
context "in a user namespace" do
let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
+ let(:wiki_page_content) { '' }
it "shows validation error message" do
- page.within(".wiki-form") do
- fill_in(:wiki_content, with: "")
+ create_page
- click_on("Create page")
- end
-
- expect(page).to have_content("The form contains the following error:").and have_content("Content can't be blank")
-
- page.within(".wiki-form") do
- fill_in(:wiki_content, with: "[link test](test)")
+ expect(page)
+ .to have_content("The form contains the following error:")
+ .and have_content("Content can't be blank")
+ .and have_css('.wiki-form')
+ .and have_css('.qa-create-page-button')
+ end
- click_on("Create page")
- end
+ it 'offers to create pages that do not yet exist' do
+ create_page(content: "[link test](test)")
- expect(page).to have_content("Home").and have_content("link test")
+ expect(page)
+ .to have_content("Home")
+ .and have_content("link test")
click_link("link test")
expect(page).to have_content("Create New Page")
end
+ it "has a link to the parent directory in the pages sidebar" do
+ wiki_full_path = "one/two/three-test"
+ create_page(title: wiki_full_path, content: 'wiki content')
+
+ wiki_page = wiki.find_page(wiki_full_path)
+ expect(wiki_page).to be_present
+ dir = wiki.find_dir(wiki_page.directory)
+ expect(dir).to be_present
+
+ expect(current_path).to include(wiki_full_path)
+
+ expect(page).to have_link(dir.slug, href: project_wiki_dir_path(project, dir))
+ end
+
it "shows non-escaped link in the pages list", :quarantine do
fill_in(:wiki_title, with: "one/two/three-test")
@@ -58,19 +104,17 @@ describe "User creates wiki page" do
expect(page).to have_xpath("//a[@href='/#{project.full_path}/wikis/one/two/three-test']")
end
- it "has `Create home` as a commit message", :js do
- wait_for_requests
-
- expect(page).to have_field("wiki[message]", with: "Create home")
- end
+ it_behaves_like 'updates commit message'
it "creates a page from the home page" do
- fill_in(:wiki_content, with: "[test](test)\n[GitLab API doc](api)\n[Rake tasks](raketasks)\n# Wiki header\n")
- fill_in(:wiki_message, with: "Adding links to wiki")
+ page_content = <<~WIKI_CONTENT
+ [test](test)
+ [GitLab API doc](api)
+ [Rake tasks](raketasks)
+ # Wiki header
+ WIKI_CONTENT
- page.within(".wiki-form") do
- click_button("Create page")
- end
+ create_page(content: page_content, message: "Adding links to wiki")
expect(current_path).to eq(project_wiki_path(project, "home"))
expect(page).to have_content("test GitLab API doc Rake tasks Wiki header")
@@ -111,7 +155,7 @@ describe "User creates wiki page" do
end
end
- it "creates ASCII wiki with LaTeX blocks", :js do
+ it "creates ASCIIdoc wiki with LaTeX blocks", :js do
stub_application_setting(plantuml_url: "http://localhost", plantuml_enabled: true)
ascii_content = <<~MD
@@ -132,37 +176,25 @@ describe "User creates wiki page" do
stem:[2+2] is 4
MD
- find("#wiki_format option[value=asciidoc]").select_option
-
- fill_in(:wiki_content, with: ascii_content)
+ find("#wiki_page_format option[value=asciidoc]").select_option
- page.within(".wiki-form") do
- click_button("Create page")
- end
+ create_page(content: ascii_content)
page.within ".md" do
expect(page).to have_selector(".katex", count: 3).and have_content("2+2 is 4")
end
end
- it_behaves_like 'wiki file attachments', :quarantine
+ it_behaves_like 'wiki file attachments'
end
- context "in a group namespace", :js do
+ context "in a group namespace" do
let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) }
- it "has `Create home` as a commit message" do
- wait_for_requests
-
- expect(page).to have_field("wiki[message]", with: "Create home")
- end
-
- it "creates a page from the home page", :quarantine do
- page.within(".wiki-form") do
- fill_in(:wiki_content, with: "My awesome wiki!")
+ it_behaves_like 'updates commit message'
- click_button("Create page")
- end
+ it "creates a page from the home page" do
+ create_page(content: "My awesome wiki!")
expect(page).to have_content("Home")
.and have_content("Last edited by #{user.name}")
@@ -178,76 +210,37 @@ describe "User creates wiki page" do
visit(project_wikis_path(project))
end
- context "in a user namespace" do
- let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
-
- context "via the `new wiki page` page" do
- it "creates a page with a single word" do
- click_link("New page")
-
- page.within(".wiki-form") do
- fill_in(:wiki_title, with: "foo")
- fill_in(:wiki_content, with: "My awesome wiki!")
- end
-
- # Commit message field should have correct value.
- expect(page).to have_field("wiki[message]", with: "Create foo")
-
- click_button("Create page")
-
- expect(page).to have_content("foo")
- .and have_content("Last edited by #{user.name}")
- .and have_content("My awesome wiki!")
- end
-
- it "creates a page with spaces in the name" do
- click_link("New page")
+ shared_examples 'creates page by slug' do |slug, unslug|
+ it "creates #{slug}" do
+ start_writing(slug)
- page.within(".wiki-form") do
- fill_in(:wiki_title, with: "Spaces in the name")
- fill_in(:wiki_content, with: "My awesome wiki!")
- end
+ # Commit message field should have correct value.
+ expect(page).to have_field(message_field, with: "Create #{unslug}")
- # Commit message field should have correct value.
- expect(page).to have_field("wiki[message]", with: "Create Spaces in the name")
+ create_page(content: "My awesome wiki!")
- click_button("Create page")
-
- expect(page).to have_content("Spaces in the name")
- .and have_content("Last edited by #{user.name}")
- .and have_content("My awesome wiki!")
- end
-
- it "creates a page with hyphens in the name" do
- click_link("New page")
-
- page.within(".wiki-form") do
- fill_in(:wiki_title, with: "hyphens-in-the-name")
- fill_in(:wiki_content, with: "My awesome wiki!")
- end
-
- # Commit message field should have correct value.
- expect(page).to have_field("wiki[message]", with: "Create hyphens in the name")
-
- page.within(".wiki-form") do
- fill_in(:wiki_content, with: "My awesome wiki!")
+ expect(page).to have_content(unslug)
+ .and have_content("Last edited by #{user.name}")
+ .and have_content("My awesome wiki!")
+ end
+ end
- click_button("Create page")
- end
+ context "in a user namespace" do
+ let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
- expect(page).to have_content("hyphens in the name")
- .and have_content("Last edited by #{user.name}")
- .and have_content("My awesome wiki!")
- end
+ context "via the `new wiki page` page" do
+ include_examples 'creates page by slug', 'foo', 'foo'
+ include_examples 'creates page by slug', 'Spaces in the name', 'Spaces in the name'
+ include_examples 'creates page by slug', 'Hyphens-in-the-name', 'Hyphens in the name'
end
it "shows the emoji autocompletion dropdown" do
- click_link("New page")
+ start_writing('text-autocomplete')
page.within(".wiki-form") do
- find("#wiki_content").native.send_keys("")
+ find("#wiki_page_content").native.send_keys("")
- fill_in(:wiki_content, with: ":")
+ fill_in(:wiki_page_content, with: ":")
end
expect(page).to have_selector(".atwho-view")
@@ -258,23 +251,9 @@ describe "User creates wiki page" do
let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) }
context "via the `new wiki page` page" do
- it "creates a page" do
- click_link("New page")
-
- page.within(".wiki-form") do
- fill_in(:wiki_title, with: "foo")
- fill_in(:wiki_content, with: "My awesome wiki!")
- end
-
- # Commit message field should have correct value.
- expect(page).to have_field("wiki[message]", with: "Create foo")
-
- click_button("Create page")
-
- expect(page).to have_content("foo")
- .and have_content("Last edited by #{user.name}")
- .and have_content("My awesome wiki!")
- end
+ include_examples 'creates page by slug', 'foo', 'foo'
+ include_examples 'creates page by slug', 'Spaces in the name', 'Spaces in the name'
+ include_examples 'creates page by slug', 'Hyphens-in-the-name', 'Hyphens in the name'
end
end
end
diff --git a/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb b/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb
index 38e5e292064..9b9d3100bf5 100644
--- a/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_deletes_wiki_page_spec.rb
@@ -6,6 +6,7 @@ describe 'User deletes wiki page', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
let(:wiki_page) { create(:wiki_page, wiki: project.wiki) }
+ let(:project_wiki) { ProjectWiki.new(project, user) }
before do
sign_in(user)
@@ -18,5 +19,6 @@ describe 'User deletes wiki page', :js do
find('.modal-footer .btn-danger').click
expect(page).to have_content('Page was successfully deleted')
+ expect(project_wiki.find_page(wiki_page.slug)).to be nil
end
end
diff --git a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
index 3f3711f9eb8..5ab44e83f73 100644
--- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
@@ -10,6 +10,13 @@ describe 'User updates wiki page' do
sign_in(user)
end
+ def create_page(attrs = {})
+ page.within('.wiki-form') do
+ attrs.each { |k, v| fill_in("wiki_page_#{k}".to_sym, with: v) }
+ click_on('Create page')
+ end
+ end
+
context 'when wiki is empty' do
before do
visit(project_wikis_path(project))
@@ -28,12 +35,7 @@ describe 'User updates wiki page' do
end
it 'updates a page that has a path', :js do
- fill_in(:wiki_title, with: 'one/two/three-test')
-
- page.within '.wiki-form' do
- fill_in(:wiki_content, with: 'wiki content')
- click_on('Create page')
- end
+ create_page(title: 'one/two/three-test', content: 'wiki content')
expect(current_path).to include('one/two/three-test')
expect(find('.wiki-pages')).to have_content('three')
@@ -72,9 +74,9 @@ describe 'User updates wiki page' do
it 'updates a page', :js do
# Commit message field should have correct value.
- expect(page).to have_field('wiki[message]', with: 'Update home')
+ expect(page).to have_field('wiki_page[message]', with: 'Update home')
- fill_in(:wiki_content, with: 'My awesome wiki!')
+ fill_in(:wiki_page_content, with: 'My awesome wiki!')
click_button('Save changes')
expect(page).to have_content('Home')
@@ -83,31 +85,31 @@ describe 'User updates wiki page' do
end
it 'updates the commit message as the title is changed', :js do
- fill_in(:wiki_title, with: 'Wiki title')
+ fill_in(:wiki_page_title, with: 'Wiki title')
- expect(page).to have_field('wiki[message]', with: 'Update Wiki title')
+ expect(page).to have_field('wiki_page[message]', with: 'Update Wiki title')
end
it 'does not allow XSS', :js do
- fill_in(:wiki_title, with: '<script>')
+ fill_in(:wiki_page_title, with: '<script>')
- expect(page).to have_field('wiki[message]', with: 'Update &lt;script&gt;')
+ expect(page).to have_field('wiki_page[message]', with: 'Update &lt;script&gt;')
end
it 'shows a validation error message' do
- fill_in(:wiki_content, with: '')
+ fill_in(:wiki_page_content, with: '')
click_button('Save changes')
expect(page).to have_selector('.wiki-form')
expect(page).to have_content('Edit Page')
expect(page).to have_content('The form contains the following error:')
expect(page).to have_content("Content can't be blank")
- expect(find('textarea#wiki_content').value).to eq('')
+ expect(find('textarea#wiki_page_content').value).to eq('')
end
it 'shows the emoji autocompletion dropdown', :js do
- find('#wiki_content').native.send_keys('')
- fill_in(:wiki_content, with: ':')
+ find('#wiki_page_content').native.send_keys('')
+ fill_in(:wiki_page_content, with: ':')
expect(page).to have_selector('.atwho-view')
end
@@ -143,9 +145,9 @@ describe 'User updates wiki page' do
it 'updates a page', :js do
# Commit message field should have correct value.
- expect(page).to have_field('wiki[message]', with: 'Update home')
+ expect(page).to have_field('wiki_page[message]', with: 'Update home')
- fill_in(:wiki_content, with: 'My awesome wiki!')
+ fill_in(:wiki_page_content, with: 'My awesome wiki!')
click_button('Save changes')
@@ -169,50 +171,43 @@ describe 'User updates wiki page' do
visit(project_wiki_edit_path(project, wiki_page))
end
- it 'moves the page to the root folder' do
- fill_in(:wiki_title, with: "/#{page_name}")
+ def edit_title!(title)
+ fill_in(:wiki_page_title, with: title)
click_button('Save changes')
+ end
+
+ it 'moves the page to the root folder' do
+ edit_title!("/#{page_name}")
expect(current_path).to eq(project_wiki_path(project, page_name))
end
it 'moves the page to other dir' do
- new_page_dir = "foo1/bar1/#{page_name}"
-
- fill_in(:wiki_title, with: new_page_dir)
-
- click_button('Save changes')
+ new_page_path = "baz/quux/#{page_name}"
+ edit_title!(new_page_path)
- expect(current_path).to eq(project_wiki_path(project, new_page_dir))
+ expect(current_path).to eq(project_wiki_path(project, new_page_path))
end
it 'remains in the same place if title has not changed' do
original_path = project_wiki_path(project, wiki_page)
-
- fill_in(:wiki_title, with: page_name)
-
- click_button('Save changes')
+ edit_title!(page_name)
expect(current_path).to eq(original_path)
end
it 'can be moved to a different dir with a different name' do
- new_page_dir = "foo1/bar1/new_page_name"
-
- fill_in(:wiki_title, with: new_page_dir)
+ new_page_path = "quux/baz/new_page_name"
+ edit_title!(new_page_path)
- click_button('Save changes')
-
- expect(current_path).to eq(project_wiki_path(project, new_page_dir))
+ expect(current_path).to eq(project_wiki_path(project, new_page_path))
end
it 'can be renamed and moved to the root folder' do
new_name = 'new_page_name'
- fill_in(:wiki_title, with: "/#{new_name}")
-
- click_button('Save changes')
+ edit_title!("/#{new_name}")
expect(current_path).to eq(project_wiki_path(project, new_name))
end
@@ -220,9 +215,7 @@ describe 'User updates wiki page' do
it 'squishes the title before creating the page' do
new_page_dir = " foo1 / bar1 / #{page_name} "
- fill_in(:wiki_title, with: new_page_dir)
-
- click_button('Save changes')
+ edit_title!(new_page_dir)
expect(current_path).to eq(project_wiki_path(project, "foo1/bar1/#{page_name}"))
end
diff --git a/spec/features/projects/wiki/user_views_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_page_spec.rb
index 77e725e7f11..af8f86106d9 100644
--- a/spec/features/projects/wiki/user_views_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_views_wiki_page_spec.rb
@@ -8,10 +8,11 @@ describe 'User views a wiki page' do
let(:user) { create(:user) }
let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
let(:path) { 'image.png' }
+ let(:wiki_content) { "Look at this [image](#{path})\n\n ![alt text](#{path})" }
let(:wiki_page) do
create(:wiki_page,
wiki: project.wiki,
- attrs: { title: 'home', content: "Look at this [image](#{path})\n\n ![alt text](#{path})" })
+ attrs: { title: 'home', content: wiki_content })
end
before do
@@ -19,17 +20,18 @@ describe 'User views a wiki page' do
sign_in(user)
end
+ def create_page(attrs = {})
+ page.within('.wiki-form') do
+ attrs.each { |k, v| fill_in("wiki_page_#{k}".to_sym, with: v) }
+ click_on('Create page')
+ end
+ end
+
context 'when wiki is empty' do
before do
visit(project_wikis_path(project))
click_link "Create your first page"
-
- fill_in(:wiki_title, with: 'one/two/three-test')
-
- page.within('.wiki-form') do
- fill_in(:wiki_content, with: 'wiki content')
- click_on('Create page')
- end
+ create_page(title: 'one/two/three-test', content: 'wiki content')
end
it 'shows the history of a page that has a path', :js do
@@ -83,24 +85,27 @@ describe 'User views a wiki page' do
context 'shows a file stored in a page' do
let(:path) { upload_file_to_wiki(project, user, 'dk.png') }
+ let(:image_path) { project_wiki_path(project, path) }
it do
- expect(page).to have_xpath("//img[@data-src='#{project.wiki.wiki_base_path}/#{path}']")
- expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/#{path}")
+ expect(page).to have_xpath("//img[@data-src='#{image_path}']")
+ expect(page).to have_link('image', href: "#{image_path}")
click_on('image')
- expect(current_path).to match("wikis/#{path}")
+ expect(current_path).to match(path)
expect(page).not_to have_xpath('/html') # Page should render the image which means there is no html involved
end
end
it 'shows the creation page if file does not exist' do
- expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/#{path}")
+ href = project_wiki_path(project, path)
+
+ expect(page).to have_link('image', href: href)
click_on('image')
- expect(current_path).to match("wikis/#{path}")
+ expect(current_path).to match(href)
expect(page).to have_content('Create New Page')
end
end
diff --git a/spec/features/projects/wiki/user_views_wiki_pages_spec.rb b/spec/features/projects/wiki/user_views_wiki_pages_spec.rb
index 6740df1d4ed..adb59c891c6 100644
--- a/spec/features/projects/wiki/user_views_wiki_pages_spec.rb
+++ b/spec/features/projects/wiki/user_views_wiki_pages_spec.rb
@@ -7,6 +7,7 @@ describe 'User views wiki pages' do
let(:user) { create(:user) }
let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
+ let(:project_wiki) { ProjectWiki.new(project, user) }
let!(:wiki_page1) do
create(:wiki_page, wiki: project.wiki, attrs: { title: '3 home', content: '3' })
@@ -17,73 +18,182 @@ describe 'User views wiki pages' do
let!(:wiki_page3) do
create(:wiki_page, wiki: project.wiki, attrs: { title: '2 home', content: '2' })
end
+ let!(:wiki_page4) do
+ create(:wiki_page, wiki: project.wiki, attrs: { title: 'sub-folder/0', content: 'a' })
+ end
+ let!(:wiki_page5) do
+ create(:wiki_page, wiki: project.wiki, attrs: { title: 'sub-folder/b', content: 'b' })
+ end
+
+ let(:page_link_selector) { 'a' }
let(:pages) do
- page.find('.wiki-pages-list').all('li').map { |li| li.find('a') }
+ page.all(".wiki-pages-list li #{page_link_selector}")
end
+ let(:wikis_allow_change_nesting) { false }
before do
+ stub_feature_flags(wikis_allow_change_nesting: wikis_allow_change_nesting)
project.add_maintainer(user)
sign_in(user)
visit(project_wikis_pages_path(project))
end
+ def sort_desc!
+ page.within('.wiki-sort-dropdown') do
+ page.find('.qa-reverse-sort').click
+ end
+ end
+
+ def sort_by_created_at!
+ page.within('.wiki-sort-dropdown') do
+ click_button('Title')
+ click_link('Created date')
+ end
+ end
+
+ shared_examples 'correctly_sorted_pages' do
+ it 'has pages displayed in correct order' do
+ displayed_texts = pages.map(&:text)
+ expect(displayed_texts).to eq expected_sequence.map(&:title)
+ end
+ end
+
context 'ordered by title' do
- let(:pages_ordered_by_title) { [wiki_page2, wiki_page3, wiki_page1] }
+ let(:sub_folder) { project_wiki.find_dir('sub-folder') }
- context 'asc' do
- it 'pages are displayed in direct order' do
- pages.each.with_index do |page_title, index|
- expect(page_title.text).to eq(pages_ordered_by_title[index].title)
+ context 'default display settings' do
+ context 'asc' do
+ let(:expected_sequence) { [wiki_page2, wiki_page3, wiki_page1, sub_folder] }
+
+ it_behaves_like 'correctly_sorted_pages'
+ end
+
+ context 'desc' do
+ before do
+ sort_desc!
end
+
+ let(:expected_sequence) { [sub_folder, wiki_page1, wiki_page3, wiki_page2] }
+
+ it_behaves_like 'correctly_sorted_pages'
end
end
- context 'desc' do
- before do
- page.within('.wiki-sort-dropdown') do
- page.find('.rspec-reverse-sort').click
+ context 'changing nesting is disabled' do
+ let(:wikis_allow_change_nesting) { false }
+
+ it 'does not display a nesting controller' do
+ expect(page).not_to have_css('.wiki-nesting-dropdown')
+ end
+ end
+
+ context 'changing nesting is enabled' do
+ let(:wikis_allow_change_nesting) { true }
+
+ it 'displays a nesting controller' do
+ expect(page).to have_css('.wiki-nesting-dropdown')
+ end
+
+ context 'tree' do
+ before do
+ page.within('.wiki-nesting-dropdown') do
+ click_link 'Show folder contents'
+ end
+ end
+
+ context 'asc' do
+ let(:expected_sequence) { [wiki_page2, wiki_page3, wiki_page1, sub_folder, wiki_page4, wiki_page5] }
+
+ it_behaves_like 'correctly_sorted_pages'
+ end
+
+ context 'desc' do
+ before do
+ sort_desc!
+ end
+
+ let(:expected_sequence) { [sub_folder, wiki_page5, wiki_page4, wiki_page1, wiki_page3, wiki_page2] }
+
+ it_behaves_like 'correctly_sorted_pages'
end
end
- it 'pages are displayed in reversed order' do
- pages.reverse_each.with_index do |page_title, index|
- expect(page_title.text).to eq(pages_ordered_by_title[index].title)
+ context 'nested' do
+ before do
+ page.within('.wiki-nesting-dropdown') do
+ click_link 'Hide folder contents'
+ end
+ end
+
+ context 'asc' do
+ let(:expected_sequence) { [wiki_page2, wiki_page3, wiki_page1, sub_folder] }
+
+ it_behaves_like 'correctly_sorted_pages'
+ end
+
+ context 'desc' do
+ before do
+ sort_desc!
+ end
+
+ let(:expected_sequence) { [sub_folder, wiki_page1, wiki_page3, wiki_page2] }
+
+ it_behaves_like 'correctly_sorted_pages'
+ end
+ end
+
+ context 'flat' do
+ before do
+ page.within('.wiki-nesting-dropdown') do
+ click_link 'Show files separately'
+ end
+ end
+
+ let(:page_link_selector) { 'a.wiki-page-title' }
+
+ context 'asc' do
+ let(:expected_sequence) { [wiki_page2, wiki_page3, wiki_page1, wiki_page4, wiki_page5] }
+
+ it_behaves_like 'correctly_sorted_pages'
+ end
+
+ context 'desc' do
+ before do
+ sort_desc!
+ end
+
+ let(:expected_sequence) { [wiki_page5, wiki_page4, wiki_page1, wiki_page3, wiki_page2] }
+
+ it_behaves_like 'correctly_sorted_pages'
end
end
end
end
context 'ordered by created_at' do
- let(:pages_ordered_by_created_at) { [wiki_page1, wiki_page2, wiki_page3] }
+ let(:pages_ordered_by_created_at) { [wiki_page1, wiki_page2, wiki_page3, wiki_page4, wiki_page5] }
before do
- page.within('.wiki-sort-dropdown') do
- click_button('Title')
- click_link('Created date')
- end
+ sort_by_created_at!
end
+ let(:page_link_selector) { 'a.wiki-page-title' }
+
context 'asc' do
- it 'pages are displayed in direct order' do
- pages.each.with_index do |page_title, index|
- expect(page_title.text).to eq(pages_ordered_by_created_at[index].title)
- end
- end
+ let(:expected_sequence) { [wiki_page1, wiki_page2, wiki_page3, wiki_page4, wiki_page5] }
+
+ it_behaves_like 'correctly_sorted_pages'
end
context 'desc' do
before do
- page.within('.wiki-sort-dropdown') do
- page.find('.rspec-reverse-sort').click
- end
+ sort_desc!
end
- it 'pages are displayed in reversed order' do
- pages.reverse_each.with_index do |page_title, index|
- expect(page_title.text).to eq(pages_ordered_by_created_at[index].title)
- end
- end
+ let(:expected_sequence) { [wiki_page5, wiki_page4, wiki_page3, wiki_page2, wiki_page1] }
+
+ it_behaves_like 'correctly_sorted_pages'
end
end
end
diff --git a/spec/frontend/wikis_spec.js b/spec/frontend/wikis_spec.js
index b2475488d97..a2b68bf866e 100644
--- a/spec/frontend/wikis_spec.js
+++ b/spec/frontend/wikis_spec.js
@@ -3,27 +3,27 @@ import { setHTMLFixture } from './helpers/fixtures';
describe('Wikis', () => {
describe('setting the commit message when the title changes', () => {
- const editFormHtmlFixture = args => `<form class="wiki-form ${
- args.newPage ? 'js-new-wiki-page' : ''
- }">
- <input type="text" id="wiki_title" value="My title" />
- <input type="text" id="wiki_message" />
- </form>`;
-
let wikis;
let titleInput;
let messageInput;
+ const CREATE = true;
+ const UPDATE = false;
- describe('when the wiki page is being created', () => {
- const formHtmlFixture = editFormHtmlFixture({ newPage: true });
+ const editFormHtmlFixture = newPage =>
+ `<form class="wiki-form ${newPage ? 'js-new-wiki-page' : ''}">
+ <input type="text" id="wiki_page_title" value="My title" />
+ <input type="text" id="wiki_page_message" />
+ </form>`;
- beforeEach(() => {
- setHTMLFixture(formHtmlFixture);
+ const init = newPage => {
+ setHTMLFixture(editFormHtmlFixture(newPage));
+ titleInput = document.getElementById('wiki_page_title');
+ messageInput = document.getElementById('wiki_page_message');
+ wikis = new Wikis();
+ };
- titleInput = document.getElementById('wiki_title');
- messageInput = document.getElementById('wiki_message');
- wikis = new Wikis();
- });
+ describe('when the wiki page is being created', () => {
+ beforeEach(() => init(CREATE));
it('binds an event listener to the title input', () => {
wikis.handleWikiTitleChange = jest.fn();
@@ -51,15 +51,7 @@ describe('Wikis', () => {
});
describe('when the wiki page is being updated', () => {
- const formHtmlFixture = editFormHtmlFixture({ newPage: false });
-
- beforeEach(() => {
- setHTMLFixture(formHtmlFixture);
-
- titleInput = document.getElementById('wiki_title');
- messageInput = document.getElementById('wiki_message');
- wikis = new Wikis();
- });
+ beforeEach(() => init(UPDATE));
it('sets the commit message when title changes, prefixing with "Update"', () => {
titleInput.value = 'My title';
diff --git a/spec/helpers/wiki_helper_spec.rb b/spec/helpers/wiki_helper_spec.rb
index bcc2bd71da1..4310e4bd22c 100644
--- a/spec/helpers/wiki_helper_spec.rb
+++ b/spec/helpers/wiki_helper_spec.rb
@@ -23,8 +23,13 @@ describe WikiHelper do
describe '#wiki_sort_controls' do
let(:project) { create(:project) }
- let(:wiki_link) { helper.wiki_sort_controls(project, sort, direction) }
- let(:classes) { "btn btn-default has-tooltip reverse-sort-btn qa-reverse-sort rspec-reverse-sort" }
+ let(:classes) { described_class::WIKI_SORT_CSS_CLASSES }
+
+ subject(:wiki_link) do
+ helper.wiki_sort_controls(sort: sort, direction: direction) do |opts|
+ project_wikis_pages_path(project, opts)
+ end
+ end
def expected_link(sort, direction, icon_class)
path = "/#{project.full_path}/wikis/pages?direction=#{direction}&sort=#{sort}"
@@ -62,6 +67,18 @@ describe WikiHelper do
end
end
+ describe '#wiki_show_children_icon' do
+ ProjectWiki::NESTINGS.each do |nesting|
+ context "When the nesting parameter is `#{nesting}`" do
+ let(:element) { helper.wiki_show_children_icon(nesting) }
+
+ it 'produces something that contains an SVG' do
+ expect(element).to match(/svg/)
+ end
+ end
+ end
+ end
+
describe '#wiki_sort_title' do
it 'returns a title corresponding to a key' do
expect(helper.wiki_sort_title('created_at')).to eq('Created date')
diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
index 4587bd85939..7a83dc3ec1d 100644
--- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
@@ -11,6 +11,10 @@ describe Banzai::Filter::WikiLinkFilter do
let(:wiki) { ProjectWiki.new(project, user) }
let(:repository_upload_folder) { Wikis::CreateAttachmentService::ATTACHMENT_PATH }
+ def upload_href(file_name)
+ ::File.join(wiki.wiki_page_path, repository_upload_folder, file_name)
+ end
+
it "doesn't rewrite absolute links" do
filtered_link = filter("<a href='http://example.com:8000/'>Link</a>", project_wiki: wiki).children[0]
@@ -28,12 +32,12 @@ describe Banzai::Filter::WikiLinkFilter do
it 'rewrites links' do
filtered_link = filter("<a href='#{repository_upload_folder}/a.test'>Link</a>", project_wiki: wiki).children[0]
- expect(filtered_link.attribute('href').value).to eq("#{wiki.wiki_base_path}/#{repository_upload_folder}/a.test")
+ expect(filtered_link.attribute('href').value).to eq(upload_href "a.test")
end
end
context 'with "img" html tag' do
- let(:path) { "#{wiki.wiki_base_path}/#{repository_upload_folder}/a.jpg" }
+ let(:path) { upload_href "a.jpg" }
context 'inside an "a" html tag' do
it 'rewrites links' do
@@ -57,7 +61,7 @@ describe Banzai::Filter::WikiLinkFilter do
it 'rewrites links' do
filtered_link = filter("<video src='#{repository_upload_folder}/a.mp4'></video>", project_wiki: wiki).children[0]
- expect(filtered_link.attribute('src').value).to eq("#{wiki.wiki_base_path}/#{repository_upload_folder}/a.mp4")
+ expect(filtered_link.attribute('src').value).to eq(upload_href "a.mp4")
end
end
@@ -65,7 +69,8 @@ describe Banzai::Filter::WikiLinkFilter do
it 'rewrites links' do
filtered_link = filter("<audio src='#{repository_upload_folder}/a.wav'></audio>", project_wiki: wiki).children[0]
- expect(filtered_link.attribute('src').value).to eq("#{wiki.wiki_base_path}/#{repository_upload_folder}/a.wav")
+ # expect(filtered_link.attribute('src').value).to eq("#{wiki.wiki_base_path}/#{repository_upload_folder}/a.wav")
+ expect(filtered_link.attribute('src').value).to eq(upload_href "a.wav")
end
end
end
diff --git a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb
index 26f2b0b0acf..7f60106cdca 100644
--- a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb
@@ -3,6 +3,12 @@
require 'spec_helper'
describe Banzai::Pipeline::WikiPipeline do
+ let_it_be(:namespace) { create(:namespace, name: "wiki_link_ns") }
+ let_it_be(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) }
+ let_it_be(:project_wiki) { ProjectWiki.new(project, double(:user)) }
+ let_it_be(:page) { build(:wiki_page, wiki: project_wiki, page: OpenStruct.new(url_path: 'nested/twice/start-page')) }
+ let(:prefix) { project_wiki.wiki_page_path }
+
describe 'TableOfContents' do
it 'replaces the tag with the TableOfContentsFilter result' do
markdown = <<-MD.strip_heredoc
@@ -54,132 +60,138 @@ describe Banzai::Pipeline::WikiPipeline do
end
describe "Links" do
- let(:namespace) { create(:namespace, name: "wiki_link_ns") }
- let(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) }
- let(:project_wiki) { ProjectWiki.new(project, double(:user)) }
- let(:page) { build(:wiki_page, wiki: project_wiki, page: OpenStruct.new(url_path: 'nested/twice/start-page')) }
-
- { "when GitLab is hosted at a root URL" => '/',
- "when GitLab is hosted at a relative URL" => '/nested/relative/gitlab' }.each do |test_name, relative_url_root|
- context test_name do
+ shared_examples 'a correct link rewrite' do
+ it 'rewrites links correctly' do
+ output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+
+ expect(output).to include("href=\"#{page_href}\"")
+ end
+ end
+
+ shared_examples 'link examples' do |test_name|
+ let(:page_href) { "#{prefix}/#{expected_page_path}" }
+
+ context "when GitLab is hosted at a #{test_name} URL" do
before do
allow(Gitlab.config.gitlab).to receive(:relative_url_root).and_return(relative_url_root)
end
describe "linking to pages within the wiki" do
- context "when creating hierarchical links to the current directory" do
- it "rewrites non-file links to be at the scope of the current directory" do
- markdown = "[Page](./page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ let(:markdown) { "[Page](#{nesting}page#{extension})" }
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page\"")
+ context "when creating hierarchical links to the current directory" do
+ let(:nesting) { './' }
+ context 'non file links' do
+ let(:extension) { '' }
+ let(:expected_page_path) { 'nested/twice/page' }
+ it_behaves_like 'a correct link rewrite'
end
- it "rewrites file links to be at the scope of the current directory" do
- markdown = "[Link to Page](./page.md)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
-
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page.md\"")
+ context 'file-like links' do
+ let(:extension) { '.md' }
+ let(:expected_page_path) { 'nested/twice/page.md' }
+ it_behaves_like 'a correct link rewrite'
end
end
context "when creating hierarchical links to the parent directory" do
- it "rewrites non-file links to be at the scope of the parent directory" do
- markdown = "[Link to Page](../page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
-
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/page\"")
+ let(:nesting) { '../' }
+ context "non file links" do
+ let(:extension) { '' }
+ let(:expected_page_path) { 'nested/page' }
+ it_behaves_like 'a correct link rewrite'
end
- it "rewrites file links to be at the scope of the parent directory" do
- markdown = "[Link to Page](../page.md)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
-
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/page.md\"")
+ context "file-like links" do
+ let(:extension) { '.md' }
+ let(:expected_page_path) { 'nested/page.md' }
+ it_behaves_like 'a correct link rewrite'
end
end
context "when creating hierarchical links to a sub-directory" do
- it "rewrites non-file links to be at the scope of the sub-directory" do
- markdown = "[Link to Page](./subdirectory/page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ let(:nesting) { './subdirectory/' }
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/subdirectory/page\"")
+ context "non file links" do
+ let(:extension) { '' }
+ let(:expected_page_path) { 'nested/twice/subdirectory/page' }
+ it_behaves_like 'a correct link rewrite'
end
- it "rewrites file links to be at the scope of the sub-directory" do
- markdown = "[Link to Page](./subdirectory/page.md)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
-
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/subdirectory/page.md\"")
+ context 'file-like links' do
+ let(:extension) { '.md' }
+ let(:expected_page_path) { 'nested/twice/subdirectory/page.md' }
+ it_behaves_like 'a correct link rewrite'
end
end
describe "when creating non-hierarchical links" do
- it 'rewrites non-file links to be at the scope of the wiki root' do
- markdown = "[Link to Page](page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ let(:nesting) { '' }
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page\"")
+ context 'non-file links' do
+ let(:extension) { '' }
+ let(:expected_page_path) { 'page' }
+ it_behaves_like 'a correct link rewrite'
end
- it 'rewrites non-file links (with spaces) to be at the scope of the wiki root' do
- markdown = "[Link to Page](page slug)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
-
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page%20slug\"")
+ context 'non-file links (with spaces)' do
+ let(:extension) { ' slug' }
+ let(:expected_page_path) { 'page%20slug' }
+ it_behaves_like 'a correct link rewrite'
end
- it "rewrites file links to be at the scope of the current directory" do
- markdown = "[Link to Page](page.md)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
-
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/nested/twice/page.md\"")
+ context "file links" do
+ let(:extension) { '.md' }
+ let(:expected_page_path) { 'nested/twice/page.md' }
+ it_behaves_like 'a correct link rewrite'
end
- it 'rewrites links with anchor' do
- markdown = '[Link to Header](start-page#title)'
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
-
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/start-page#title\"")
+ context 'links with anchor' do
+ let(:extension) { '#title' }
+ let(:expected_page_path) { 'page#title' }
+ it_behaves_like 'a correct link rewrite'
end
- it 'rewrites links (with spaces) with anchor' do
- markdown = '[Link to Header](start page#title)'
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
-
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/start%20page#title\"")
+ context 'links (with spaces) with anchor' do
+ let(:extension) { ' two#title' }
+ let(:expected_page_path) { 'page%20two#title' }
+ it_behaves_like 'a correct link rewrite'
end
end
describe "when creating root links" do
- it 'rewrites non-file links to be at the scope of the wiki root' do
- markdown = "[Link to Page](/page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ let(:nesting) { '/' }
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page\"")
+ context 'non-file links' do
+ let(:extension) { '' }
+ let(:expected_page_path) { 'page' }
+ it_behaves_like 'a correct link rewrite'
end
- it 'rewrites file links to be at the scope of the wiki root' do
- markdown = "[Link to Page](/page.md)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
-
- expect(output).to include("href=\"#{relative_url_root}/wiki_link_ns/wiki_link_project/wikis/page.md\"")
+ context 'file links' do
+ let(:extension) { '.md' }
+ let(:expected_page_path) { 'page.md' }
+ it_behaves_like 'a correct link rewrite'
end
end
end
describe "linking to pages outside the wiki (absolute)" do
- it "doesn't rewrite links" do
- markdown = "[Link to Page](http://example.com/page)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
-
- expect(output).to include('href="http://example.com/page"')
- end
+ let(:markdown) { "[Link to Page](http://example.com/page)" }
+ let(:page_href) { 'http://example.com/page' }
+ it_behaves_like 'a correct link rewrite'
end
end
end
+ include_examples 'link examples', :root do
+ let(:relative_url_root) { '/' }
+ end
+
+ include_examples 'link examples', :relative do
+ let(:relative_url_root) { '/nested/relative/gitlab' }
+ end
+
describe "checking slug validity when assembling links" do
context "with a valid slug" do
let(:valid_slug) { "http://example.com" }
@@ -261,37 +273,54 @@ describe Banzai::Pipeline::WikiPipeline do
end
describe 'videos and audio' do
- let_it_be(:namespace) { create(:namespace, name: "wiki_link_ns") }
- let_it_be(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) }
- let_it_be(:project_wiki) { ProjectWiki.new(project, double(:user)) }
- let_it_be(:page) { build(:wiki_page, wiki: project_wiki, page: OpenStruct.new(url_path: 'nested/twice/start-page')) }
+ def src(file_name)
+ "#{prefix}/nested/twice/#{file_name}"
+ end
- it 'generates video html structure' do
- markdown = "![video_file](video_file_name.mp4)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ shared_examples 'correct video rewrite' do
+ let(:markdown) { "![video_file](#{file_name})" }
+ let(:video_fragment) { "<video src=\"#{prefix}/#{expected_file_path}\"" }
+ let(:options) do
+ {
+ project: project,
+ project_wiki: project_wiki,
+ page_slug: page.slug
+ }
+ end
+
+ it 'generates video html structure' do
+ output = described_class.to_html(markdown, options)
- expect(output).to include('<video src="/wiki_link_ns/wiki_link_project/wikis/nested/twice/video_file_name.mp4"')
+ expect(output).to include(video_fragment)
+ end
end
- it 'rewrites and replaces video links names with white spaces to %20' do
- markdown = "![video file](video file name.mp4)"
- output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
+ context 'underscores' do
+ let(:file_name) { 'video_file_name.mp4' }
+ let(:expected_file_path) { 'nested/twice/video_file_name.mp4' }
+ it_behaves_like 'correct video rewrite'
+ end
- expect(output).to include('<video src="/wiki_link_ns/wiki_link_project/wikis/nested/twice/video%20file%20name.mp4"')
+ context 'spaces' do
+ let(:file_name) { 'video file name.mp4' }
+ let(:expected_file_path) { 'nested/twice/video%20file%20name.mp4' }
+ it_behaves_like 'correct video rewrite'
end
it 'generates audio html structure' do
markdown = "![audio_file](audio_file_name.wav)"
+ safe_name = "audio_file_name.wav"
output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
- expect(output).to include('<audio src="/wiki_link_ns/wiki_link_project/wikis/nested/twice/audio_file_name.wav"')
+ expect(output).to include(%Q'<audio src="#{src(safe_name)}"')
end
it 'rewrites and replaces audio links names with white spaces to %20' do
markdown = "![audio file](audio file name.wav)"
+ safe_name = "audio%20file%20name.wav"
output = described_class.to_html(markdown, project: project, project_wiki: project_wiki, page_slug: page.slug)
- expect(output).to include('<audio src="/wiki_link_ns/wiki_link_project/wikis/nested/twice/audio%20file%20name.wav"')
+ expect(output).to include(%Q'<audio src="#{src(safe_name)}"')
end
end
end
diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb
index 08d3c638f9e..4ed2c232f97 100644
--- a/spec/lib/gitlab/url_builder_spec.rb
+++ b/spec/lib/gitlab/url_builder_spec.rb
@@ -150,7 +150,7 @@ describe Gitlab::UrlBuilder do
wiki_page = build(:wiki_page)
url = described_class.build(wiki_page)
- expect(url).to eq "#{Gitlab.config.gitlab.url}#{wiki_page.wiki.wiki_base_path}/#{wiki_page.slug}"
+ expect(url).to eq "#{Gitlab.config.gitlab.url}#{wiki_page.wiki.wiki_page_path}/#{wiki_page.slug}"
end
end
end
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index 890918d4a7c..a68434c8c66 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -252,4 +252,41 @@ describe Gitlab::Utils do
expect(described_class.string_to_ip_object('1:0:0:0:0:0:0:0/124')).to eq(IPAddr.new('1:0:0:0:0:0:0:0/124'))
end
end
+
+ describe '.allow_hash_values' do
+ it 'removes keys that do not pass the inclusion filters' do
+ symbols = %i[x y z]
+ ints = (0..100)
+ strings = %w[foo bar baz].to_set
+
+ hash = {
+ a: :x,
+ b: 100,
+ c: 'foo',
+ d: :irrelevant,
+ aa: :w,
+ bb: 200,
+ cc: 'food',
+ dd: :totally_irrelevant
+ }
+ allowed = {
+ a: symbols,
+ b: ints,
+ c: strings,
+ aa: symbols,
+ bb: ints,
+ cc: strings
+ }
+
+ described_class.allow_hash_values(hash, allowed)
+
+ expect(hash).to eq({
+ a: :x,
+ b: 100,
+ c: 'foo',
+ d: :irrelevant,
+ dd: :totally_irrelevant
+ })
+ end
+ end
end
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index 31d1d1fd7d1..f5c827e5a29 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -28,7 +28,9 @@ describe ProjectWiki do
describe '#web_url' do
it 'returns the full web URL to the wiki' do
- expect(subject.web_url).to eq("#{Gitlab.config.gitlab.url}/#{project.full_path}/wikis/home")
+ home_url = Gitlab::Routing.url_helpers.project_wiki_url(project, :home)
+
+ expect(subject.web_url).to eq(home_url)
end
end
@@ -71,9 +73,23 @@ describe ProjectWiki do
describe "#wiki_base_path" do
it "returns the wiki base path" do
- wiki_base_path = "#{Gitlab.config.gitlab.relative_url_root}/#{project.full_path}/wikis"
+ wiki_path = Gitlab::Routing.url_helpers.project_wikis_path(project)
+
+ expect(subject.wiki_base_path).to eq(wiki_path)
+ end
+ end
- expect(subject.wiki_base_path).to eq(wiki_base_path)
+ describe "#wiki_page_path" do
+ let(:page) { create(:wiki_page, wiki: project_wiki) }
+
+ describe 'suffixed with /:page_slug' do
+ subject { "#{project_wiki.wiki_page_path}/#{page.slug}" }
+
+ it "equals the project_wiki_path" do
+ path = Gitlab::Routing.url_helpers.project_wiki_path(project, page)
+
+ expect(subject).to eq(path)
+ end
end
end
diff --git a/spec/models/wiki_directory_spec.rb b/spec/models/wiki_directory_spec.rb
index 5fbcccf897e..aff21888605 100644
--- a/spec/models/wiki_directory_spec.rb
+++ b/spec/models/wiki_directory_spec.rb
@@ -1,14 +1,94 @@
# frozen_string_literal: true
require 'spec_helper'
+require 'set'
RSpec.describe WikiDirectory do
+ include GitHelpers
+
+ let(:project) { create(:project, :wiki_repo) }
+ let(:user) { project.owner }
+ let(:wiki) { ProjectWiki.new(project, user) }
+
describe 'validations' do
subject { build(:wiki_directory) }
it { is_expected.to validate_presence_of(:slug) }
end
+ describe '.group_by_directory' do
+ context 'when there are no pages' do
+ it 'returns an empty array' do
+ expect(described_class.group_by_directory(nil)).to eq([])
+ expect(described_class.group_by_directory([])).to eq([])
+ end
+ end
+
+ context 'when there are pages' do
+ before do
+ create_page('dir_1/dir_1_1/page_3', 'content')
+ create_page('page_1', 'content')
+ create_page('dir_1/page_2', 'content')
+ create_page('dir_2', 'page with dir name')
+ create_page('dir_2/page_5', 'content')
+ create_page('page_6', 'content')
+ create_page('dir_2/page_4', 'content')
+ end
+
+ let(:page_1) { wiki.find_page('page_1') }
+ let(:page_6) { wiki.find_page('page_6') }
+ let(:page_dir_2) { wiki.find_page('dir_2') }
+
+ let(:dir_1) do
+ described_class.new('dir_1', [wiki.find_page('dir_1/page_2')])
+ end
+ let(:dir_1_1) do
+ described_class.new('dir_1/dir_1_1', [wiki.find_page('dir_1/dir_1_1/page_3')])
+ end
+ let(:dir_2) do
+ pages = [wiki.find_page('dir_2/page_5'),
+ wiki.find_page('dir_2/page_4')]
+ described_class.new('dir_2', pages)
+ end
+
+ context "#list_pages" do
+ shared_examples "a correct grouping" do
+ let(:grouped_slugs) { grouped_entries.map(&method(:slugs)) }
+ let(:expected_slugs) { expected_grouped_entries.map(&method(:slugs)).map(&method(:match_array)) }
+
+ it 'returns an array with pages and directories' do
+ expect(grouped_slugs).to match_array(expected_slugs)
+ end
+ end
+
+ context 'sort by title' do
+ let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages) }
+
+ let(:expected_grouped_entries) { [dir_1_1, dir_1, page_dir_2, dir_2, page_1, page_6] }
+
+ it_behaves_like "a correct grouping"
+ end
+
+ context 'sort by created_at' do
+ let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages(sort: 'created_at')) }
+ let(:expected_grouped_entries) { [dir_1_1, page_1, dir_1, page_dir_2, dir_2, page_6] }
+
+ it_behaves_like "a correct grouping"
+ end
+
+ it 'returns an array with retained order with directories at the top' do
+ expected_order = ['dir_1/dir_1_1/page_3', 'dir_1/page_2', 'dir_2', 'dir_2/page_4', 'dir_2/page_5', 'page_1', 'page_6']
+
+ grouped_entries = described_class.group_by_directory(wiki.list_pages)
+
+ actual_order = grouped_entries.flat_map(&method(:slugs))
+
+ expect(actual_order).to eq(expected_order)
+ end
+ end
+ end
+ end
+
describe '#initialize' do
context 'when there are pages' do
let(:pages) { [build(:wiki_page)] }
@@ -40,7 +120,112 @@ RSpec.describe WikiDirectory do
it 'returns the relative path to the partial to be used' do
directory = build(:wiki_directory)
- expect(directory.to_partial_path).to eq('projects/wikis/wiki_directory')
+ expect(directory.to_partial_path).to eq('projects/wiki_directories/wiki_directory')
+ end
+ end
+
+ describe 'attributes' do
+ def page_path(index)
+ "dir-path/page-#{index}"
+ end
+
+ let(:page_paths) { (1..3).map { |n| page_path(n) } }
+
+ let(:pages) do
+ page_paths.map { |p| wiki.find_page(p) }
end
+
+ subject { described_class.new('dir-path', pages) }
+
+ context 'there are no pages' do
+ let(:pages) { [] }
+
+ it { is_expected.to have_attributes(page_count: 0, last_version: be_nil) }
+ end
+
+ context 'there is one page' do
+ before do
+ create_page("dir-path/singleton", "Just this page")
+ end
+
+ let(:the_page) { wiki.find_page("dir-path/singleton") }
+ let(:pages) { [the_page] }
+
+ it { is_expected.to have_attributes(page_count: 1, last_version: the_page.last_version) }
+ end
+
+ context 'there are a few pages, each with a single version' do
+ before do
+ page_paths.each_with_index do |path, n|
+ Timecop.freeze(Time.local(1990) + n.minutes) do
+ create_page(path, "this is page #{n}")
+ end
+ end
+ end
+
+ let(:expected_last_version) { pages.last.last_version }
+
+ it { is_expected.to have_attributes(page_count: 3, last_version: expected_last_version) }
+ end
+
+ context 'there are a few pages, each with a few versions' do
+ before do
+ page_paths.each_with_index do |path, n|
+ t = Time.local(1990) + n.minutes
+ Timecop.freeze(t) do
+ create_page(path, "This is page #{n}")
+ (2..3).each do |v|
+ Timecop.freeze(t + v.seconds) do
+ update_page(path, "Now at version #{v}")
+ end
+ end
+ end
+ end
+ end
+
+ it { is_expected.to have_attributes(page_count: 3, last_version: pages.last.last_version) }
+ end
+ end
+
+ private
+
+ def create_page(name, content)
+ wiki.wiki.write_page(name, :markdown, content, commit_details)
+ set_time(name)
+ end
+
+ def update_page(name, content)
+ wiki.wiki.update_page(name, name, :markdown, content, update_commit_details)
+ set_time(name)
+ end
+
+ def set_time(name)
+ return unless Timecop.frozen?
+
+ new_date = Time.now
+ page = wiki.find_page(name).page
+ commit = page.version.commit
+ repo = commit.instance_variable_get(:@repository)
+
+ rug_commit = rugged_repo_at_path(repo.relative_path).lookup(commit.id)
+ rug_commit.amend(
+ message: rug_commit.message,
+ tree: rug_commit.tree,
+ author: rug_commit.author.merge(time: new_date),
+ committer: rug_commit.committer.merge(time: new_date),
+ update_ref: 'HEAD'
+ )
+ end
+
+ def commit_details
+ Gitlab::Git::Wiki::CommitDetails.new(user.id, user.username, user.name, user.email, "test commit")
+ end
+
+ def update_commit_details
+ Gitlab::Git::Wiki::CommitDetails.new(user.id, user.username, user.name, user.email, "test update")
+ end
+
+ def slugs(thing)
+ Array.wrap(thing.respond_to?(:pages) ? thing.pages.map(&:slug) : thing.slug)
end
end
diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb
index 18c62c917dc..8f3730f97ac 100644
--- a/spec/models/wiki_page_spec.rb
+++ b/spec/models/wiki_page_spec.rb
@@ -9,87 +9,6 @@ describe WikiPage do
subject { described_class.new(wiki) }
- describe '.group_by_directory' do
- context 'when there are no pages' do
- it 'returns an empty array' do
- expect(described_class.group_by_directory(nil)).to eq([])
- expect(described_class.group_by_directory([])).to eq([])
- end
- end
-
- context 'when there are pages' do
- before do
- create_page('dir_1/dir_1_1/page_3', 'content')
- create_page('page_1', 'content')
- create_page('dir_1/page_2', 'content')
- create_page('dir_2', 'page with dir name')
- create_page('dir_2/page_5', 'content')
- create_page('page_6', 'content')
- create_page('dir_2/page_4', 'content')
- end
-
- let(:page_1) { wiki.find_page('page_1') }
- let(:page_6) { wiki.find_page('page_6') }
- let(:page_dir_2) { wiki.find_page('dir_2') }
-
- let(:dir_1) do
- WikiDirectory.new('dir_1', [wiki.find_page('dir_1/page_2')])
- end
- let(:dir_1_1) do
- WikiDirectory.new('dir_1/dir_1_1', [wiki.find_page('dir_1/dir_1_1/page_3')])
- end
- let(:dir_2) do
- pages = [wiki.find_page('dir_2/page_5'),
- wiki.find_page('dir_2/page_4')]
- WikiDirectory.new('dir_2', pages)
- end
-
- context "#list_pages" do
- context 'sort by title' do
- let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages) }
- let(:expected_grouped_entries) { [dir_1_1, dir_1, page_dir_2, dir_2, page_1, page_6] }
-
- it 'returns an array with pages and directories' do
- grouped_entries.each_with_index do |page_or_dir, i|
- expected_page_or_dir = expected_grouped_entries[i]
- expected_slugs = get_slugs(expected_page_or_dir)
- slugs = get_slugs(page_or_dir)
-
- expect(slugs).to match_array(expected_slugs)
- end
- end
- end
-
- context 'sort by created_at' do
- let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages(sort: 'created_at')) }
- let(:expected_grouped_entries) { [dir_1_1, page_1, dir_1, page_dir_2, dir_2, page_6] }
-
- it 'returns an array with pages and directories' do
- grouped_entries.each_with_index do |page_or_dir, i|
- expected_page_or_dir = expected_grouped_entries[i]
- expected_slugs = get_slugs(expected_page_or_dir)
- slugs = get_slugs(page_or_dir)
-
- expect(slugs).to match_array(expected_slugs)
- end
- end
- end
-
- it 'returns an array with retained order with directories at the top' do
- expected_order = ['dir_1/dir_1_1/page_3', 'dir_1/page_2', 'dir_2', 'dir_2/page_4', 'dir_2/page_5', 'page_1', 'page_6']
-
- grouped_entries = described_class.group_by_directory(wiki.list_pages)
-
- actual_order =
- grouped_entries.flat_map do |page_or_dir|
- get_slugs(page_or_dir)
- end
- expect(actual_order).to eq(expected_order)
- end
- end
- end
- end
-
describe '.unhyphenize' do
it 'removes hyphens from a name' do
name = 'a-name--with-hyphens'
@@ -505,7 +424,7 @@ describe WikiPage do
it 'returns the relative path to the partial to be used' do
page = build(:wiki_page)
- expect(page.to_partial_path).to eq('projects/wikis/wiki_page')
+ expect(page.to_partial_path).to eq('projects/wiki_pages/wiki_page')
end
end
@@ -585,12 +504,4 @@ describe WikiPage do
page = wiki.wiki.page(title: title, dir: dir)
wiki.delete_page(page, "test commit")
end
-
- def get_slugs(page_or_dir)
- if page_or_dir.is_a? WikiPage
- [page_or_dir.slug]
- else
- page_or_dir.pages.present? ? page_or_dir.pages.map(&:slug) : []
- end
- end
end
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index acdbf064a73..3e57bb70287 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -3,9 +3,12 @@ require 'spec_helper'
describe 'project routing' do
before do
allow(Project).to receive(:find_by_full_path).and_return(false)
- allow(Project).to receive(:find_by_full_path).with('gitlab/gitlabhq', any_args).and_return(true)
+ allow(Project).to receive(:find_by_full_path).with('gitlab/gitlabhq', any_args).and_return(project)
end
+ set(:namespace) { create(:namespace, name: 'gitlab') }
+ set(:project) { create(:project, namespace: namespace, name: 'gitlabhq') }
+
# Shared examples for a resource inside a Project
#
# By default it tests all the default REST actions: index, create, new, edit,
@@ -145,24 +148,39 @@ describe 'project routing' do
it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/autocomplete_sources/labels", "/gitlab/gitlabhq/-/autocomplete_sources/labels"
end
- # pages_project_wikis GET /:project_id/wikis/pages(.:format) projects/wikis#pages
- # history_project_wiki GET /:project_id/wikis/:id/history(.:format) projects/wikis#history
- # project_wikis POST /:project_id/wikis(.:format) projects/wikis#create
- # edit_project_wiki GET /:project_id/wikis/:id/edit(.:format) projects/wikis#edit
- # project_wiki GET /:project_id/wikis/:id(.:format) projects/wikis#show
- # DELETE /:project_id/wikis/:id(.:format) projects/wikis#destroy
+ # GET /:project_id/wikis/pages(.:format) projects/wikis#pages
+ # GET /:project_id/-/wiki_pages/:id/history(.:format) projects/wiki_pages#history
+ # POST /:project_id/-/wiki_pages(.:format) projects/wiki_pages#create
+ # GET /:project_id/-/wiki_pages/:id/edit(.:format) projects/wiki_pages#edit
+ # GET /:project_id/-/wiki_pages/:id(.:format) projects/wiki_pages#show
+ # DELETE /:project_id/-/wiki_pages/:id(.:format) projects/wiki_pages#destroy
describe Projects::WikisController, 'routing' do
- it 'to #pages' do
- expect(get('/gitlab/gitlabhq/wikis/pages')).to route_to('projects/wikis#pages', namespace_id: 'gitlab', project_id: 'gitlabhq')
+ let(:wiki) { ProjectWiki.new(project, project.owner) }
+ let(:wiki_page) { create(:wiki_page, wiki: wiki) }
+
+ it '#pages' do
+ expect(get('/gitlab/gitlabhq/wikis/pages'))
+ .to route_to('projects/wikis#pages',
+ namespace_id: 'gitlab',
+ project_id: 'gitlabhq')
end
- it 'to #history' do
- expect(get('/gitlab/gitlabhq/wikis/1/history')).to route_to('projects/wikis#history', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
+ describe '#history' do
+ let(:history_path) { project_wiki_history_path(project, wiki_page) }
+
+ it 'routes to history' do
+ expect(get(history_path))
+ .to route_to('projects/wiki_pages#history',
+ namespace_id: namespace.path,
+ project_id: project.name,
+ id: wiki_page.slug)
+ end
end
it_behaves_like 'RESTful project resources' do
let(:actions) { [:create, :edit, :show, :destroy] }
- let(:controller) { 'wikis' }
+ let(:controller) { 'wiki_pages' }
+ let(:controller_path) { '-/wiki_pages' }
end
end
diff --git a/spec/routing/wiki_routing_spec.rb b/spec/routing/wiki_routing_spec.rb
new file mode 100644
index 00000000000..94349dbaa74
--- /dev/null
+++ b/spec/routing/wiki_routing_spec.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# We build URIs to wiki pages manually in various places (most notably
+# in markdown generation). To ensure these do not get out of sync, these
+# tests verify that our path generation assumptions are sound.
+describe 'Wiki path generation assumptions' do
+ set(:project) { create(:project, :public, :repository) }
+
+ let(:project_wiki) { ProjectWiki.new(project, project.owner) }
+ let(:some_page_name) { 'some-wiki-page' }
+ let(:wiki_page) do
+ create(:wiki_page, wiki: project_wiki, attrs: { title: some_page_name })
+ end
+
+ describe 'WikiProject#wiki_page_path', 'routing' do
+ it 'is consistent with routing to wiki#show' do
+ uri = URI.parse(project_wiki.wiki_page_path)
+ path = ::File.join(uri.path, some_page_name)
+
+ expect(get('/' + path)).to route_to('projects/wiki_pages#show',
+ id: some_page_name,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param)
+ end
+ end
+
+ describe 'project_wiki_path', 'routing' do
+ describe 'GET' do
+ it 'routes to the :show action' do
+ path = project_wiki_path(project, wiki_page)
+
+ expect(get('/' + path)).to route_to('projects/wiki_pages#show',
+ id: wiki_page.slug,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param)
+ end
+ end
+ end
+
+ describe 'project_wiki_pages_new_path', 'routing' do
+ describe 'GET' do
+ it 'routes to the :new action' do
+ path = project_wiki_pages_new_path(project)
+
+ expect(get('/' + path)).to route_to('projects/wiki_pages#new',
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param)
+ end
+ end
+ end
+
+ # Early versions of the wiki paths routed all wiki pages at
+ # /wikis/:id - this test exists to guarantee that we support
+ # old URIs that may be out there, saved in bookmarks, on other wikis, etc.
+ describe 'legacy route support', type: 'request' do
+ let(:path) { ::File.join(project_wikis_path(project), some_page_name) }
+
+ before do
+ get(path)
+ end
+
+ it 'routes to new wiki paths' do
+ dest = project_wiki_path(project, wiki_page)
+
+ expect(response).to redirect_to(dest)
+ end
+
+ context 'the page is nested in a directory' do
+ let(:some_page_name) { 'some-dir/some-deep-dir/some-page' }
+ let(:path) { ::File.join(project_wikis_path(project), some_page_name) }
+
+ it 'still routes correctly' do
+ dest = project_wiki_path(project, wiki_page)
+
+ expect(response).to redirect_to(dest)
+ end
+ end
+
+ context 'the user requested the old history path' do
+ let(:some_page_name) { 'some-dir/some-deep-dir/some-page' }
+ let(:path) { ::File.join(project_wikis_path(project), some_page_name, 'history') }
+
+ it 'redirects to the new history path' do
+ dest = project_wiki_history_path(project, wiki_page)
+
+ expect(response).to redirect_to(dest)
+ end
+ end
+
+ context 'the user requested the old edit path' do
+ let(:some_page_name) { 'some-dir/some-deep-dir/some-page' }
+ let(:path) { ::File.join(project_wikis_path(project), some_page_name, 'edit') }
+
+ it 'redirects to the new history path' do
+ dest = project_wiki_edit_path(project, wiki_page)
+
+ expect(response).to redirect_to(dest)
+ end
+ end
+ end
+end
diff --git a/spec/support/controllers/authorization_helpers.rb b/spec/support/controllers/authorization_helpers.rb
new file mode 100644
index 00000000000..e1786e0ca8a
--- /dev/null
+++ b/spec/support/controllers/authorization_helpers.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+def forbid_controller_ability!(ability)
+ allow(controller).to receive(:can?).and_call_original
+ allow(controller).to receive(:can?).with(anything, ability, any_args).and_return(false)
+end
diff --git a/spec/support/helpers/capybara_helpers.rb b/spec/support/helpers/capybara_helpers.rb
index a7baa7042c9..13ec179b734 100644
--- a/spec/support/helpers/capybara_helpers.rb
+++ b/spec/support/helpers/capybara_helpers.rb
@@ -46,4 +46,14 @@ module CapybaraHelpers
def javascript_test?
Capybara.current_driver == Capybara.javascript_driver
end
+
+ def scroll_to(element)
+ raise 'JS not available' unless javascript_test?
+
+ script = <<-JS
+ arguments[0].scrollIntoView(true);
+ JS
+
+ page.driver.browser.execute_script(script, element.native)
+ end
end
diff --git a/spec/support/helpers/dropzone_helper.rb b/spec/support/helpers/dropzone_helper.rb
index a0f261b312e..3f37673dadd 100644
--- a/spec/support/helpers/dropzone_helper.rb
+++ b/spec/support/helpers/dropzone_helper.rb
@@ -14,6 +14,8 @@ module DropzoneHelper
# If it's 'false', then the helper will NOT wait for backend response
# It lets to test behaviors while AJAX is processing.
def dropzone_file(files, max_file_size = 0, wait_for_queuecomplete = true)
+ # Assert that there is a dropzone to use (waiting until it is ready)
+ expect(page).to have_css('.div-dropzone')
# Generate a fake file input that Capybara can attach to
page.execute_script <<-JS.strip_heredoc
$('#fakeFileInput').remove();
diff --git a/spec/support/helpers/git_helpers.rb b/spec/support/helpers/git_helpers.rb
index 99c5871ba54..05e31a1154a 100644
--- a/spec/support/helpers/git_helpers.rb
+++ b/spec/support/helpers/git_helpers.rb
@@ -2,8 +2,11 @@
module GitHelpers
def rugged_repo(repository)
- path = File.join(TestEnv.repos_path, repository.disk_path + '.git')
+ rugged_repo_at_path(repository.disk_path + '.git')
+ end
+ def rugged_repo_at_path(relative_path)
+ path = File.join(TestEnv.repos_path, relative_path)
Rugged::Repository.new(path)
end
end
diff --git a/spec/support/helpers/wiki_helpers.rb b/spec/support/helpers/wiki_helpers.rb
index 06cea728b42..0cf70fd4ef7 100644
--- a/spec/support/helpers/wiki_helpers.rb
+++ b/spec/support/helpers/wiki_helpers.rb
@@ -12,4 +12,10 @@ module WikiHelpers
::Wikis::CreateAttachmentService.new(project, user, opts)
.execute[:result][:file_path]
end
+
+ # Generate the form field name for a given attribute of an object.
+ # This is rather general, but is currently only used in the wiki featur tests.
+ def form_field_name(obj, attr_name)
+ "#{ActiveModel::Naming.param_key(obj)}[#{attr_name}]"
+ end
end
diff --git a/spec/support/matchers/issuable_matchers.rb b/spec/support/matchers/issuable_matchers.rb
index 743f0b8c932..ab15a80bf60 100644
--- a/spec/support/matchers/issuable_matchers.rb
+++ b/spec/support/matchers/issuable_matchers.rb
@@ -2,7 +2,8 @@
RSpec::Matchers.define :have_header_with_correct_id_and_link do |level, text, id, parent = ".md"|
match do |actual|
- node = find("#{parent} h#{level} a#user-content-#{id}")
+ # anchors may be invisible
+ node = find("#{parent} h#{level} a#user-content-#{id}", visible: false)
expect(node[:href]).to end_with("##{id}")
diff --git a/spec/support/shared_examples/wiki_file_attachments_examples.rb b/spec/support/shared_examples/wiki_file_attachments_examples.rb
index 22fbfb48928..a43b7c0300f 100644
--- a/spec/support/shared_examples/wiki_file_attachments_examples.rb
+++ b/spec/support/shared_examples/wiki_file_attachments_examples.rb
@@ -42,7 +42,7 @@ shared_examples 'wiki file attachments' do
end
end
- context 'uploading is complete', :quarantine do
+ context 'uploading is complete' do
it 'shows "Attach a file" button on uploading complete' do
attach_with_dropzone
wait_for_requests
@@ -52,11 +52,11 @@ shared_examples 'wiki file attachments' do
end
it 'the markdown link is added to the page' do
- fill_in(:wiki_content, with: '')
+ fill_in(:wiki_page_content, with: '')
attach_with_dropzone(true)
wait_for_requests
- expect(page.find('#wiki_content').value)
+ expect(page.find('#wiki_page_content').value)
.to match(%r{\!\[dk\]\(uploads/\h{32}/dk\.png\)$})
end
@@ -70,7 +70,7 @@ shared_examples 'wiki file attachments' do
img_link = page.find('a.no-attachment-icon img')['src']
expect(link).to eq img_link
- expect(URI.parse(link).path).to eq File.join(wiki.wiki_base_path, file_path)
+ expect(URI.parse(link).path).to eq File.join(wiki.wiki_page_path, file_path)
end
it 'the file has been added to the wiki repository' do