diff options
Diffstat (limited to 'spec/support/shared_examples/features/wiki')
11 files changed, 1290 insertions, 0 deletions
diff --git a/spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb b/spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb new file mode 100644 index 00000000000..0ef1ccdfe57 --- /dev/null +++ b/spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +# Requires a context containing: +# wiki + +RSpec.shared_examples 'wiki file attachments' do + include DropzoneHelper + + context 'uploading attachments', :js do + def attach_with_dropzone(wait = false) + dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, wait) + end + + context 'before uploading' do + it 'shows "Attach a file" button' do + expect(page).to have_button('Attach a file') + expect(page).not_to have_selector('.uploading-progress-container', visible: true) + end + end + + context 'uploading is in progress', :capybara_ignore_server_errors do + it 'cancels uploading on clicking to "Cancel" button' do + slow_requests do + attach_with_dropzone + + click_button 'Cancel' + end + + expect(page).to have_button('Attach a file') + expect(page).not_to have_button('Cancel') + expect(page).not_to have_selector('.uploading-progress-container', visible: true) + end + + it 'shows "Attaching a file" message on uploading 1 file' do + slow_requests do + attach_with_dropzone + + expect(page).to have_selector('.attaching-file-message', visible: true, text: 'Attaching a file -') + end + end + end + + context 'uploading is complete' do + it 'shows "Attach a file" button on uploading complete' do + attach_with_dropzone + wait_for_requests + + expect(page).to have_button('Attach a file') + expect(page).not_to have_selector('.uploading-progress-container', visible: true) + end + + it 'the markdown link is added to the page' do + fill_in(:wiki_content, with: '') + attach_with_dropzone(true) + wait_for_requests + + expect(page.find('#wiki_content').value) + .to match(%r{\!\[dk\]\(uploads/\h{32}/dk\.png\)$}) + end + + it 'the links point to the wiki root url' do + attach_with_dropzone(true) + wait_for_requests + + find('.js-md-preview-button').click + file_path = page.find('input[name="files[]"]', visible: :hidden).value + link = page.find('a.no-attachment-icon')['href'] + 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) + end + + it 'the file has been added to the wiki repository' do + expect do + attach_with_dropzone(true) + wait_for_requests + end.to change { wiki.repository.ls_files('HEAD').count }.by(1) + + file_path = page.find('input[name="files[]"]', visible: :hidden).value + + expect(wiki.find_file(file_path, 'HEAD').path).not_to be_nil + end + end + end +end diff --git a/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb new file mode 100644 index 00000000000..44d82d2e753 --- /dev/null +++ b/spec/support/shared_examples/features/wiki/user_creates_wiki_page_shared_examples.rb @@ -0,0 +1,245 @@ +# frozen_string_literal: true + +# Requires a context containing: +# wiki +# user + +RSpec.shared_examples 'User creates wiki page' do + include WikiHelpers + + before do + sign_in(user) + end + + context "when wiki is empty" do + before do |example| + visit wiki_path(wiki) + + wait_for_svg_to_be_loaded(example) + + click_link "Create your first page" + end + + it "shows validation error message" do + page.within(".wiki-form") do + fill_in(:wiki_content, with: "") + + 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)") + + click_on("Create page") + end + + 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 "shows non-escaped link in the pages list" 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 + + expect(current_path).to include("one/two/three-test") + expect(page).to have_link(href: wiki_page_path(wiki, '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 "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.within(".wiki-form") do + click_button("Create page") + end + + expect(current_path).to eq(wiki_page_path(wiki, "home")) + expect(page).to have_content("test GitLab API doc Rake tasks Wiki header") + .and have_content("Home") + .and have_content("Last edited by #{user.name}") + .and have_header_with_correct_id_and_link(1, "Wiki header", "wiki-header") + + click_link("test") + + expect(current_path).to eq(wiki_page_path(wiki, "test")) + + page.within(:css, ".nav-text") do + expect(page).to have_content("Create New Page") + end + + click_link("Home") + + expect(current_path).to eq(wiki_page_path(wiki, "home")) + + click_link("GitLab API") + + expect(current_path).to eq(wiki_page_path(wiki, "api")) + + page.within(:css, ".nav-text") do + expect(page).to have_content("Create") + end + + click_link("Home") + + expect(current_path).to eq(wiki_page_path(wiki, "home")) + + click_link("Rake tasks") + + expect(current_path).to eq(wiki_page_path(wiki, "raketasks")) + + page.within(:css, ".nav-text") do + expect(page).to have_content("Create") + end + end + + it "creates ASCII wiki with LaTeX blocks", :js do + stub_application_setting(plantuml_url: "http://localhost", plantuml_enabled: true) + + ascii_content = <<~MD + :stem: latexmath + + [stem] + ++++ + \\sqrt{4} = 2 + ++++ + + another part + + [latexmath] + ++++ + \\beta_x \\gamma + ++++ + + stem:[2+2] is 4 + MD + + find("#wiki_format option[value=asciidoc]").select_option + + fill_in(:wiki_content, with: ascii_content) + + page.within(".wiki-form") do + click_button("Create page") + end + + page.within ".md" do + expect(page).to have_selector(".katex", count: 3).and have_content("2+2 is 4") + end + end + + it 'creates a wiki page with Org markup', :aggregate_failures do + org_content = <<~ORG + * Heading + ** Subheading + [[home][Link to Home]] + ORG + + page.within('.wiki-form') do + find('#wiki_format option[value=org]').select_option + fill_in(:wiki_content, with: org_content) + click_button('Create page') + end + + expect(page).to have_selector('h1', text: 'Heading') + expect(page).to have_selector('h2', text: 'Subheading') + expect(page).to have_link(href: wiki_page_path(wiki, 'home')) + end + + it_behaves_like 'wiki file attachments' + end + + context "when wiki is not empty", :js do + before do + create(:wiki_page, wiki: wiki, title: 'home', content: 'Home page') + + visit wiki_path(wiki) + end + + 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") + + 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("wiki[message]", with: "Create Spaces in the name") + + 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!") + + click_button("Create page") + end + + expect(page).to have_content("hyphens in the name") + .and have_content("Last edited by #{user.name}") + .and have_content("My awesome wiki!") + end + end + + it "shows the emoji autocompletion dropdown" do + click_link("New page") + + page.within(".wiki-form") do + find("#wiki_content").native.send_keys("") + + fill_in(:wiki_content, with: ":") + end + + expect(page).to have_selector(".atwho-view") + end + end +end diff --git a/spec/support/shared_examples/features/wiki/user_deletes_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_deletes_wiki_page_shared_examples.rb new file mode 100644 index 00000000000..e1fd9c8dbec --- /dev/null +++ b/spec/support/shared_examples/features/wiki/user_deletes_wiki_page_shared_examples.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# Requires a context containing: +# wiki +# user + +RSpec.shared_examples 'User deletes wiki page' do + include WikiHelpers + + let(:wiki_page) { create(:wiki_page, wiki: wiki) } + + before do + sign_in(user) + visit wiki_page_path(wiki, wiki_page) + end + + it 'deletes a page', :js do + click_on('Edit') + click_on('Delete') + find('.modal-footer .btn-danger').click + + expect(page).to have_content('Page was successfully deleted') + end +end diff --git a/spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb new file mode 100644 index 00000000000..cf6ae6cfa5b --- /dev/null +++ b/spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true + +# Requires a context containing: +# wiki +# user + +RSpec.shared_examples 'User previews wiki changes' do + let(:wiki_page) { build(:wiki_page, wiki: wiki) } + + before do + sign_in(user) + end + + shared_examples 'relative links' do + let_it_be(:page_content) do + <<~HEREDOC + Some text so key event for [ does not trigger an incorrect replacement. + [regular link](regular) + [relative link 1](../relative) + [relative link 2](./relative) + [relative link 3](./e/f/relative) + [spaced link](title with spaces) + HEREDOC + end + + def relative_path(path) + (Pathname.new(wiki.wiki_base_path) + File.dirname(wiki_page.path).tr(' ', '-') + path).to_s + end + + shared_examples "rewrites relative links" do + specify do + expect(element).to have_link('regular link', href: wiki.wiki_base_path + '/regular') + expect(element).to have_link('spaced link', href: wiki.wiki_base_path + '/title%20with%20spaces') + + expect(element).to have_link('relative link 1', href: relative_path('../relative')) + expect(element).to have_link('relative link 2', href: relative_path('./relative')) + expect(element).to have_link('relative link 3', href: relative_path('./e/f/relative')) + end + end + + context "when there are no spaces or hyphens in the page name" do + let(:wiki_page) { build(:wiki_page, wiki: wiki, title: 'a/b/c/d', content: page_content) } + + it_behaves_like 'rewrites relative links' + end + + context "when there are spaces in the page name" do + let(:wiki_page) { build(:wiki_page, wiki: wiki, title: 'a page/b page/c page/d page', content: page_content) } + + it_behaves_like 'rewrites relative links' + end + + context "when there are hyphens in the page name" do + let(:wiki_page) { build(:wiki_page, wiki: wiki, title: 'a-page/b-page/c-page/d-page', content: page_content) } + + it_behaves_like 'rewrites relative links' + end + end + + context "when rendering a new wiki page", :js do + before do + wiki_page.create # rubocop:disable Rails/SaveBang + visit wiki_page_path(wiki, wiki_page) + end + + it_behaves_like 'relative links' do + let(:element) { page.find('.js-wiki-page-content') } + end + end + + context "when previewing an existing wiki page", :js do + let(:preview) { page.find('.md-preview-holder') } + + before do + wiki_page.create # rubocop:disable Rails/SaveBang + visit wiki_page_path(wiki, wiki_page, action: :edit) + end + + it_behaves_like 'relative links' do + before do + click_on 'Preview' + end + + let(:element) { preview } + end + + it 'renders content with CommonMark' do + fill_in :wiki_content, with: "1. one\n - sublist\n" + click_on "Preview" + + # the above generates two separate lists (not embedded) in CommonMark + expect(preview).to have_content("sublist") + expect(preview).not_to have_xpath("//ol//li//ul") + end + + it "does not linkify double brackets inside code blocks as expected" do + fill_in :wiki_content, with: <<-HEREDOC + `[[do_not_linkify]]` + ``` + [[also_do_not_linkify]] + ``` + HEREDOC + click_on "Preview" + + expect(preview).to have_content("do_not_linkify") + expect(preview).to have_content('[[do_not_linkify]]') + expect(preview).to have_content('[[also_do_not_linkify]]') + end + end +end diff --git a/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb new file mode 100644 index 00000000000..fee455207f1 --- /dev/null +++ b/spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb @@ -0,0 +1,231 @@ +# frozen_string_literal: true + +# Requires a context containing: +# wiki +# user + +RSpec.shared_examples 'User updates wiki page' do + include WikiHelpers + + before do + sign_in(user) + end + + context 'when wiki is empty' do + before do |example| + visit(wiki_path(wiki)) + + wait_for_svg_to_be_loaded(example) + + click_link "Create your first page" + end + + it 'redirects back to the home edit page' do + page.within(:css, '.wiki-form .form-actions') do + click_on('Cancel') + end + + expect(current_path).to eq wiki_path(wiki) + 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 + + expect(current_path).to include('one/two/three-test') + expect(find('.wiki-pages')).to have_content('three') + + first(:link, text: 'three').click + + expect(find('.nav-text')).to have_content('three') + + click_on('Edit') + + expect(current_path).to include('one/two/three-test') + expect(page).to have_content('Edit Page') + + fill_in('Content', with: 'Updated Wiki Content') + click_on('Save changes') + + expect(page).to have_content('Updated Wiki Content') + end + + it_behaves_like 'wiki file attachments' + end + + context 'when wiki is not empty' do + let!(:wiki_page) { create(:wiki_page, wiki: wiki, title: 'home', content: 'Home page') } + + before do + visit(wiki_path(wiki)) + + click_link('Edit') + end + + it 'updates a page', :js do + # Commit message field should have correct value. + expect(page).to have_field('wiki[message]', with: 'Update home') + + fill_in(:wiki_content, with: 'My awesome wiki!') + click_button('Save changes') + + expect(page).to have_content('Home') + expect(page).to have_content("Last edited by #{user.name}") + expect(page).to have_content('My awesome wiki!') + end + + it 'updates the commit message as the title is changed', :js do + fill_in(:wiki_title, with: '& < > \ \ { } &') + + expect(page).to have_field('wiki[message]', with: 'Update & < > \ \ { } &') + end + + it 'correctly escapes the commit message entities', :js do + fill_in(:wiki_title, with: 'Wiki title') + + expect(page).to have_field('wiki[message]', with: 'Update Wiki title') + end + + it 'shows a validation error message' do + fill_in(:wiki_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('') + end + + it 'shows the emoji autocompletion dropdown', :js do + find('#wiki_content').native.send_keys('') + fill_in(:wiki_content, with: ':') + + expect(page).to have_selector('.atwho-view') + end + + it 'shows the error message' do + wiki_page.update(content: 'Update') # rubocop:disable Rails/SaveBang + + click_button('Save changes') + + expect(page).to have_content('Someone edited the page the same time you did.') + end + + it 'updates a page' do + fill_in('Content', with: 'Updated Wiki Content') + click_on('Save changes') + + expect(page).to have_content('Updated Wiki Content') + end + + it 'cancels editing of a page' do + page.within(:css, '.wiki-form .form-actions') do + click_on('Cancel') + end + + expect(current_path).to eq(wiki_page_path(wiki, wiki_page)) + end + + it_behaves_like 'wiki file attachments' + end + + context 'when the page is in a subdir' do + let(:page_name) { 'page_name' } + let(:page_dir) { "foo/bar/#{page_name}" } + let!(:wiki_page) { create(:wiki_page, wiki: wiki, title: page_dir, content: 'Home page') } + + before do + visit wiki_page_path(wiki, wiki_page, action: :edit) + end + + it 'moves the page to the root folder' do + fill_in(:wiki_title, with: "/#{page_name}") + + click_button('Save changes') + + expect(current_path).to eq(wiki_page_path(wiki, 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') + + expect(current_path).to eq(wiki_page_path(wiki, new_page_dir)) + end + + it 'remains in the same place if title has not changed' do + original_path = wiki_page_path(wiki, wiki_page) + + fill_in(:wiki_title, with: page_name) + + click_button('Save changes') + + 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) + + click_button('Save changes') + + expect(current_path).to eq(wiki_page_path(wiki, new_page_dir)) + 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') + + expect(current_path).to eq(wiki_page_path(wiki, new_name)) + end + + 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') + + expect(current_path).to eq(wiki_page_path(wiki, "foo1/bar1/#{page_name}")) + end + + it_behaves_like 'wiki file attachments' + end + + context 'when an existing page exceeds the content size limit' do + let!(:wiki_page) { create(:wiki_page, wiki: wiki, content: "one\ntwo\nthree") } + + before do + stub_application_setting(wiki_page_max_content_bytes: 10) + + visit wiki_page_path(wiki_page.wiki, wiki_page, action: :edit) + end + + it 'allows changing the title if the content does not change' do + fill_in 'Title', with: 'new title' + click_on 'Save changes' + + expect(page).to have_content('Wiki was successfully updated.') + end + + it 'shows a validation error when trying to change the content' do + fill_in 'Content', with: 'new content' + click_on 'Save changes' + + expect(page).to have_content('The form contains the following error:') + expect(page).to have_content('Content is too long (11 Bytes). The maximum size is 10 Bytes.') + end + end +end diff --git a/spec/support/shared_examples/features/wiki/user_uses_wiki_shortcuts_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_uses_wiki_shortcuts_shared_examples.rb new file mode 100644 index 00000000000..0330b345a18 --- /dev/null +++ b/spec/support/shared_examples/features/wiki/user_uses_wiki_shortcuts_shared_examples.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +# Requires a context containing: +# wiki +# user + +RSpec.shared_examples 'User uses wiki shortcuts' do + let(:wiki_page) { create(:wiki_page, wiki: wiki, title: 'home', content: 'Home page') } + + before do + sign_in(user) + visit wiki_page_path(wiki, wiki_page) + end + + it 'Visit edit wiki page using "e" keyboard shortcut', :js do + find('body').native.send_key('e') + + expect(find('.wiki-page-title')).to have_content('Edit Page') + end +end diff --git a/spec/support/shared_examples/features/wiki/user_views_asciidoc_page_with_includes_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_asciidoc_page_with_includes_shared_examples.rb new file mode 100644 index 00000000000..3b2fda4e05b --- /dev/null +++ b/spec/support/shared_examples/features/wiki/user_views_asciidoc_page_with_includes_shared_examples.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'User views AsciiDoc page with includes' do + let_it_be(:wiki_content_selector) { '[data-qa-selector=wiki_page_content]' } + let!(:included_wiki_page) { create_wiki_page('included_page', content: 'Content from the included page')} + let!(:wiki_page) { create_wiki_page('home', content: "Content from the main page.\ninclude::included_page.asciidoc[]") } + + def create_wiki_page(title, content:) + attrs = { + title: title, + content: content, + format: :asciidoc + } + + create(:wiki_page, wiki: wiki, **attrs) + end + + before do + sign_in(user) + end + + context 'when the file being included exists', :js do + it 'includes the file contents' do + visit(wiki_page_path(wiki, wiki_page)) + + page.within(:css, wiki_content_selector) do + expect(page).to have_content('Content from the main page. Content from the included page') + end + end + + context 'when there are multiple versions of the wiki pages' do + before do + # rubocop:disable Rails/SaveBang + included_wiki_page.update(message: 'updated included file', content: 'Updated content from the included page') + wiki_page.update(message: 'updated wiki page', content: "Updated content from the main page.\ninclude::included_page.asciidoc[]") + # rubocop:enable Rails/SaveBang + end + + let(:latest_version_id) { wiki_page.versions.first.id } + let(:oldest_version_id) { wiki_page.versions.last.id } + + context 'viewing the latest version' do + it 'includes the latest content' do + visit(wiki_page_path(wiki, wiki_page, version_id: latest_version_id)) + + page.within(:css, wiki_content_selector) do + expect(page).to have_content('Updated content from the main page. Updated content from the included page') + end + end + end + + context 'viewing the original version' do + it 'includes the content from the original version' do + visit(wiki_page_path(wiki, wiki_page, version_id: oldest_version_id)) + + page.within(:css, wiki_content_selector) do + expect(page).to have_content('Content from the main page. Content from the included page') + end + end + end + end + end + + context 'when the file being included does not exist', :js do + before do + included_wiki_page.delete + end + + it 'outputs an error' do + visit(wiki_page_path(wiki, wiki_page)) + + page.within(:css, wiki_content_selector) do + expect(page).to have_content('Content from the main page. [ERROR: include::included_page.asciidoc[] - unresolved directive]') + end + end + end +end diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb new file mode 100644 index 00000000000..d7f5b485a82 --- /dev/null +++ b/spec/support/shared_examples/features/wiki/user_views_wiki_empty_shared_examples.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +# Requires a context containing: +# wiki + +RSpec.shared_examples 'User views empty wiki' do + let(:element) { page.find('.row.empty-state') } + let(:container_name) { wiki.container.class.name.humanize(capitalize: false) } + let(:confluence_link) { 'Enable the Confluence Wiki integration' } + + shared_examples 'wiki is not found' do + it 'shows an error message' do + visit wiki_path(wiki) + + if @current_user + expect(page).to have_content('Page Not Found') + else + expect(page).to have_content('You need to sign in') + end + end + end + + shared_examples 'empty wiki message' do |writable: false, issuable: false, confluence: false| + # This mirrors the logic in: + # - app/views/shared/empty_states/_wikis.html.haml + # - WikiHelper#wiki_empty_state_messages + it 'shows the empty state message with the expected elements' do + visit wiki_path(wiki) + + if writable + expect(element).to have_content("The wiki lets you write documentation for your #{container_name}") + else + expect(element).to have_content("This #{container_name} has no wiki pages") + expect(element).to have_content("You must be a #{container_name} member") + end + + if issuable && !writable + expect(element).to have_content("improve the wiki for this #{container_name}") + expect(element).to have_link("issue tracker", href: project_issues_path(project)) + expect(element).to have_link("Suggest wiki improvement", href: new_project_issue_path(project)) + else + expect(element).not_to have_content("improve the wiki for this #{container_name}") + expect(element).not_to have_link("issue tracker") + expect(element).not_to have_link("Suggest wiki improvement") + end + + if confluence + expect(element).to have_link(confluence_link) + else + expect(element).not_to have_link(confluence_link) + end + + if writable + element.click_link 'Create your first page' + + expect(page).to have_button('Create page') + else + expect(element).not_to have_link('Create your first page') + end + end + end +end diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb new file mode 100644 index 00000000000..40998ebde4c --- /dev/null +++ b/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb @@ -0,0 +1,278 @@ +# frozen_string_literal: true + +# Requires a context containing: +# wiki +# user + +RSpec.shared_examples 'User views a wiki page' do + include WikiHelpers + + let(:path) { 'image.png' } + let(:wiki_page) do + create(:wiki_page, + wiki: wiki, + title: 'home', content: "Look at this [image](#{path})\n\n ![alt text](#{path})") + end + + before do + sign_in(user) + end + + context 'when wiki is empty', :js do + before do + visit wiki_path(wiki) + + wait_for_svg_to_be_loaded + + 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 + + expect(page).to have_content('Wiki was successfully updated.') + end + + it 'shows the history of a page that has a path' do + expect(current_path).to include('one/two/three-test') + + first(:link, text: 'three').click + click_on('Page history') + + expect(current_path).to include('one/two/three-test') + + page.within(:css, '.nav-text') do + expect(page).to have_content('History') + end + end + + it 'shows an old version of a page' do + expect(current_path).to include('one/two/three-test') + expect(find('.wiki-pages')).to have_content('three') + + first(:link, text: 'three').click + + expect(find('.nav-text')).to have_content('three') + + click_on('Edit') + + expect(current_path).to include('one/two/three-test') + expect(page).to have_content('Edit Page') + + fill_in('Content', with: 'Updated Wiki Content') + click_on('Save changes') + + expect(page).to have_content('Wiki was successfully updated.') + + click_on('Page history') + + within('.nav-text') do + expect(page).to have_content('History') + end + + within('.wiki-history') do + expect(page).to have_css('a[href*="?version_id"]', count: 4) + end + end + end + + context 'when a page does not have history' do + before do + visit(wiki_page_path(wiki, wiki_page)) + end + + it 'shows all the pages' do + expect(page).to have_content(user.name) + expect(find('.wiki-pages')).to have_content(wiki_page.title.capitalize) + end + + context 'shows a file stored in a page' do + let(:path) { upload_file_to_wiki(wiki, user, 'dk.png') } + + it do + expect(page).to have_xpath("//img[@data-src='#{wiki.wiki_base_path}/#{path}']") + expect(page).to have_link('image', href: "#{wiki.wiki_base_path}/#{path}") + + click_on('image') + + expect(current_path).to match("wikis/#{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: "#{wiki.wiki_base_path}/#{path}") + + click_on('image') + + expect(current_path).to match("wikis/#{path}") + expect(page).to have_content('Create New Page') + end + end + + context 'when a page has history' do + before do + wiki_page.update(message: 'updated home', content: 'updated [some link](other-page)') # rubocop:disable Rails/SaveBang + end + + it 'shows the page history' do + visit(wiki_page_path(wiki, wiki_page)) + + expect(page).to have_selector('a.btn', text: 'Edit') + + click_on('Page history') + + expect(page).to have_content(user.name) + expect(page).to have_content("#{user.username} created page: home") + expect(page).to have_content('updated home') + end + + it 'does not show the "Edit" button' do + visit(wiki_page_path(wiki, wiki_page, version_id: wiki_page.versions.last.id)) + + expect(page).not_to have_selector('a.btn', text: 'Edit') + end + + context 'show the diff' do + before do + skip('Diffing for group wikis will be implemented in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42610') if wiki.container.is_a?(Group) + end + + def expect_diff_links(commit) + diff_path = wiki_page_path(wiki, wiki_page, version_id: commit, action: :diff) + + expect(page).to have_link('Hide whitespace changes', href: "#{diff_path}&w=1") + expect(page).to have_link('Inline', href: "#{diff_path}&view=inline") + expect(page).to have_link('Side-by-side', href: "#{diff_path}&view=parallel") + expect(page).to have_link("View page @ #{commit.short_id}", href: wiki_page_path(wiki, wiki_page, version_id: commit)) + expect(page).to have_css('.diff-file[data-blob-diff-path="%s"]' % diff_path) + end + + it 'links to the correct diffs' do + visit wiki_page_path(wiki, wiki_page, action: :history) + + commit1 = wiki.commit('HEAD^') + commit2 = wiki.commit + + expect(page).to have_link('created page: home', href: wiki_page_path(wiki, wiki_page, version_id: commit1, action: :diff)) + expect(page).to have_link('updated home', href: wiki_page_path(wiki, wiki_page, version_id: commit2, action: :diff)) + end + + it 'between the current and the previous version of a page' do + commit = wiki.commit + visit wiki_page_path(wiki, wiki_page, version_id: commit, action: :diff) + + expect(page).to have_content('by John Doe') + expect(page).to have_content('updated home') + expect(page).to have_content('Showing 1 changed file with 1 addition and 3 deletions') + expect(page).to have_content('some link') + + expect_diff_links(commit) + end + + it 'between two old versions of a page' do + wiki_page.update(message: 'latest home change', content: 'updated [another link](other-page)') # rubocop:disable Rails/SaveBang: + commit = wiki.commit('HEAD^') + visit wiki_page_path(wiki, wiki_page, version_id: commit, action: :diff) + + expect(page).to have_content('by John Doe') + expect(page).to have_content('updated home') + expect(page).to have_content('Showing 1 changed file with 1 addition and 3 deletions') + expect(page).to have_content('some link') + expect(page).not_to have_content('latest home change') + expect(page).not_to have_content('another link') + + expect_diff_links(commit) + end + + it 'for the oldest version of a page' do + commit = wiki.commit('HEAD^') + visit wiki_page_path(wiki, wiki_page, version_id: commit, action: :diff) + + expect(page).to have_content('by John Doe') + expect(page).to have_content('created page: home') + expect(page).to have_content('Showing 1 changed file with 4 additions and 0 deletions') + expect(page).to have_content('Look at this') + + expect_diff_links(commit) + end + end + end + + context 'when a page has special characters in its title' do + let(:title) { '<foo> !@#$%^&*()[]{}=_+\'"\\|<>? <bar>' } + + before do + wiki_page.update(title: title ) # rubocop:disable Rails/SaveBang + end + + it 'preserves the special characters' do + visit(wiki_page_path(wiki, wiki_page)) + + expect(page).to have_css('.wiki-page-title', text: title) + expect(page).to have_css('.wiki-pages li', text: title) + end + end + + context 'when a page has XSS in its title or content' do + let(:title) { '<script>alert("title")<script>' } + + before do + wiki_page.update(title: title, content: 'foo <script>alert("content")</script> bar') # rubocop:disable Rails/SaveBang + end + + it 'safely displays the page' do + visit(wiki_page_path(wiki, wiki_page)) + + expect(page).to have_css('.wiki-page-title', text: title) + expect(page).to have_content('foo bar') + end + end + + context 'when a page has XSS in its message' do + before do + wiki_page.update(message: '<script>alert(true)<script>', content: 'XSS update') # rubocop:disable Rails/SaveBang + end + + it 'safely displays the message' do + visit(wiki_page_path(wiki, wiki_page, action: :history)) + + expect(page).to have_content('<script>alert(true)<script>') + end + end + + context 'when page has invalid content encoding' do + let(:content) { (+'whatever').force_encoding('ISO-8859-1') } + + before do + allow(Gitlab::EncodingHelper).to receive(:encode!).and_return(content) + + visit(wiki_page_path(wiki, wiki_page)) + end + + it 'does not show "Edit" button' do + expect(page).not_to have_selector('a.btn', text: 'Edit') + end + + it 'shows error' do + page.within(:css, '.flash-notice') do + expect(page).to have_content('The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.') + end + end + end + + it 'opens a default wiki page', :js do + visit wiki.container.web_url + + find('.shortcuts-wiki').click + + wait_for_svg_to_be_loaded + + click_link "Create your first page" + + expect(page).to have_content('Create New Page') + end +end diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_pages_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_pages_shared_examples.rb new file mode 100644 index 00000000000..314c2074eee --- /dev/null +++ b/spec/support/shared_examples/features/wiki/user_views_wiki_pages_shared_examples.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +# Requires a context containing: +# wiki +# user + +RSpec.shared_examples 'User views wiki pages' do + include WikiHelpers + + let!(:wiki_page1) do + create(:wiki_page, wiki: wiki, title: '3 home', content: '3') + end + + let!(:wiki_page2) do + create(:wiki_page, wiki: wiki, title: '1 home', content: '1') + end + + let!(:wiki_page3) do + create(:wiki_page, wiki: wiki, title: '2 home', content: '2') + end + + let(:pages) do + page.find('.wiki-pages-list').all('li').map { |li| li.find('a') } + end + + before do + sign_in(user) + visit(wiki_path(wiki, action: :pages)) + end + + context 'ordered by title' do + let(:pages_ordered_by_title) { [wiki_page2, wiki_page3, wiki_page1] } + + 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) + end + end + end + + context 'desc' do + before do + page.within('.wiki-sort-dropdown') do + page.find('.rspec-reverse-sort').click + 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) + end + end + end + end + + context 'ordered by created_at' do + let(:pages_ordered_by_created_at) { [wiki_page1, wiki_page2, wiki_page3] } + + before do + page.within('.wiki-sort-dropdown') do + click_button('Title') + click_link('Created date') + end + end + + 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 + end + + context 'desc' do + before do + page.within('.wiki-sort-dropdown') do + page.find('.rspec-reverse-sort').click + 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_created_at[index].title) + end + end + end + end +end diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_sidebar_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_sidebar_shared_examples.rb new file mode 100644 index 00000000000..a7ba7a8ad07 --- /dev/null +++ b/spec/support/shared_examples/features/wiki/user_views_wiki_sidebar_shared_examples.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +# Requires a context containing: +# wiki +# user + +RSpec.shared_examples 'User views wiki sidebar' do + include WikiHelpers + + before do + sign_in(user) + end + + context 'when there are some existing pages' do + before do + create(:wiki_page, wiki: wiki, title: 'home', content: 'home') + create(:wiki_page, wiki: wiki, title: 'another', content: 'another') + end + + it 'renders a default sidebar when there is no customized sidebar' do + visit wiki_path(wiki) + + expect(page).to have_content('another') + expect(page).not_to have_link('View All Pages') + end + + context 'when there is a customized sidebar' do + before do + create(:wiki_page, wiki: wiki, title: '_sidebar', content: 'My customized sidebar') + end + + it 'renders my customized sidebar instead of the default one' do + visit wiki_path(wiki) + + expect(page).to have_content('My customized sidebar') + expect(page).not_to have_content('Another') + end + end + end + + context 'when there are 15 existing pages' do + before do + (1..5).each { |i| create(:wiki_page, wiki: wiki, title: "my page #{i}") } + (6..10).each { |i| create(:wiki_page, wiki: wiki, title: "parent/my page #{i}") } + (11..15).each { |i| create(:wiki_page, wiki: wiki, title: "grandparent/parent/my page #{i}") } + end + + it 'shows all pages in the sidebar' do + visit wiki_path(wiki) + + (1..15).each { |i| expect(page).to have_content("my page #{i}") } + expect(page).not_to have_link('View All Pages') + end + + context 'when there are more than 15 existing pages' do + before do + create(:wiki_page, wiki: wiki, title: 'my page 16') + end + + it 'shows the first 15 pages in the sidebar' do + visit wiki_path(wiki) + + expect(page).to have_text('my page', count: 15) + expect(page).to have_link('View All Pages') + end + end + end +end |