diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-21 07:08:36 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-10-21 07:08:36 +0000 |
commit | 48aff82709769b098321c738f3444b9bdaa694c6 (patch) | |
tree | e00c7c43e2d9b603a5a6af576b1685e400410dee /spec/support/shared_examples/features | |
parent | 879f5329ee916a948223f8f43d77fba4da6cd028 (diff) | |
download | gitlab-ce-48aff82709769b098321c738f3444b9bdaa694c6.tar.gz |
Add latest changes from gitlab-org/gitlab@13-5-stable-eev13.5.0-rc42
Diffstat (limited to 'spec/support/shared_examples/features')
20 files changed, 1452 insertions, 35 deletions
diff --git a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb index c9910487798..2fff4137934 100644 --- a/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb +++ b/spec/support/shared_examples/features/editable_merge_request_shared_examples.rb @@ -11,6 +11,15 @@ RSpec.shared_examples 'an editable merge request' do expect(page).to have_content user.name end + find('.js-reviewer-search').click + page.within '.dropdown-menu-user' do + click_link user.name + end + expect(find('input[name="merge_request[reviewer_ids][]"]', visible: false).value).to match(user.id.to_s) + page.within '.js-reviewer-search' do + expect(page).to have_content user.name + end + click_button 'Milestone' page.within '.issue-milestone' do click_link milestone.title @@ -38,6 +47,10 @@ RSpec.shared_examples 'an editable merge request' do expect(page).to have_content user.name end + page.within '.reviewer' do + expect(page).to have_content user.name + end + page.within '.milestone' do expect(page).to have_content milestone.title end @@ -69,7 +82,7 @@ RSpec.shared_examples 'an editable merge request' do end it 'warns about version conflict' do - merge_request.update(title: "New title") + merge_request.update!(title: "New title") fill_in 'merge_request_title', with: 'bug 345' fill_in 'merge_request_description', with: 'bug description' @@ -124,16 +137,3 @@ end def get_textarea_height page.evaluate_script('document.getElementById("merge_request_description").offsetHeight') end - -RSpec.shared_examples 'an editable merge request with reviewers' do - it 'updates merge request', :js do - find('.js-reviewer-search').click - page.within '.dropdown-menu-user' do - click_link user.name - end - expect(find('input[name="merge_request[reviewer_ids][]"]', visible: false).value).to match(user.id.to_s) - page.within '.js-reviewer-search' do - expect(page).to have_content user.name - end - end -end diff --git a/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb b/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb new file mode 100644 index 00000000000..ac1cc2da7e3 --- /dev/null +++ b/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'issuable invite members experiments' do + context 'when invite_members_version_a experiment is enabled' do + before do + stub_experiment_for_user(invite_members_version_a: true) + end + + it 'shows a link for inviting members and follows through to the members page' do + project.add_maintainer(user) + visit issuable_path + + find('.block.assignee .edit-link').click + + wait_for_requests + + page.within '.dropdown-menu-user' do + expect(page).to have_link('Invite Members', href: project_project_members_path(project)) + expect(page).to have_selector('[data-track-event="click_invite_members"]') + expect(page).to have_selector('[data-track-label="edit_assignee"]') + end + + click_link 'Invite Members' + + expect(current_path).to eq project_project_members_path(project) + end + end + + context 'when invite_members_version_b experiment is enabled' do + before do + stub_experiment_for_user(invite_members_version_b: true) + end + + it 'shows a link for inviting members and follows through to modal' do + project.add_developer(user) + visit issuable_path + + find('.block.assignee .edit-link').click + + wait_for_requests + + page.within '.dropdown-menu-user' do + expect(page).to have_link('Invite Members', href: '#') + expect(page).to have_selector('[data-track-event="click_invite_members_version_b"]') + expect(page).to have_selector('[data-track-label="edit_assignee"]') + end + + click_link 'Invite Members' + + expect(page).to have_content("Oops, this feature isn't ready yet") + end + end + + context 'when no invite members experiments are enabled' do + it 'shows author in assignee dropdown and no invite link' do + project.add_maintainer(user) + visit issuable_path + + find('.block.assignee .edit-link').click + + wait_for_requests + + page.within '.dropdown-menu-user' do + expect(page).not_to have_link('Invite Members') + end + end + end +end diff --git a/spec/support/shared_examples/features/multiple_assignees_mr_shared_examples.rb b/spec/support/shared_examples/features/multiple_assignees_mr_shared_examples.rb index 19a5750cf6d..9d023d9514a 100644 --- a/spec/support/shared_examples/features/multiple_assignees_mr_shared_examples.rb +++ b/spec/support/shared_examples/features/multiple_assignees_mr_shared_examples.rb @@ -38,7 +38,7 @@ RSpec.shared_examples 'multiple assignees merge request' do |action, save_button page.within '.issuable-sidebar' do page.within '.assignee' do # Closing dropdown to persist - click_link 'Edit' + click_link 'Apply' expect(page).to have_content user2.name end diff --git a/spec/support/shared_examples/features/multiple_reviewers_mr_shared_examples.rb b/spec/support/shared_examples/features/multiple_reviewers_mr_shared_examples.rb new file mode 100644 index 00000000000..48cde90bd9b --- /dev/null +++ b/spec/support/shared_examples/features/multiple_reviewers_mr_shared_examples.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'multiple reviewers merge request' do |action, save_button_title| + it "#{action} a MR with multiple reviewers", :js do + find('.js-reviewer-search').click + page.within '.dropdown-menu-user' do + click_link user.name + click_link user2.name + end + + # Extra click needed in order to toggle the dropdown + find('.js-reviewer-search').click + + expect(all('input[name="merge_request[reviewer_ids][]"]', visible: false).map(&:value)) + .to match_array([user.id.to_s, user2.id.to_s]) + + page.within '.js-reviewer-search' do + expect(page).to have_content "#{user2.name} + 1 more" + end + + click_button save_button_title + + page.within '.issuable-sidebar' do + page.within '.reviewer' do + expect(page).to have_content '2 Reviewers' + + click_link 'Edit' + + expect(page).to have_content user.name + expect(page).to have_content user2.name + end + end + + page.within '.dropdown-menu-user' do + click_link user.name + end + + page.within '.issuable-sidebar' do + page.within '.reviewer' do + # Closing dropdown to persist + click_link 'Edit' + + expect(page).to have_content user2.name + end + end + end +end diff --git a/spec/support/shared_examples/features/navbar_shared_examples.rb b/spec/support/shared_examples/features/navbar_shared_examples.rb index 91a4048fa7c..c768e95c45a 100644 --- a/spec/support/shared_examples/features/navbar_shared_examples.rb +++ b/spec/support/shared_examples/features/navbar_shared_examples.rb @@ -3,12 +3,14 @@ RSpec.shared_examples 'verified navigation bar' do let(:expected_structure) do structure.compact! - structure.each { |s| s[:nav_sub_items].compact! } + structure.each { |s| s[:nav_sub_items]&.compact! } structure end it 'renders correctly' do current_structure = page.all('.sidebar-top-level-items > li', class: ['!hidden']).map do |item| + next if item.find_all('a').empty? + nav_item = item.find_all('a').first.text.gsub(/\s+\d+$/, '') # remove counts at the end nav_sub_items = item.all('.sidebar-sub-level-items > li', class: ['!fly-out-top-item']).map do |list_item| @@ -16,7 +18,7 @@ RSpec.shared_examples 'verified navigation bar' do end { nav_item: nav_item, nav_sub_items: nav_sub_items } - end + end.compact expect(current_structure).to eq(expected_structure) end diff --git a/spec/support/shared_examples/features/packages_shared_examples.rb b/spec/support/shared_examples/features/packages_shared_examples.rb index f201421e827..4d2e13aa5bc 100644 --- a/spec/support/shared_examples/features/packages_shared_examples.rb +++ b/spec/support/shared_examples/features/packages_shared_examples.rb @@ -84,11 +84,11 @@ RSpec.shared_examples 'shared package sorting' do let(:packages) { [package_two, package_one] } end - it_behaves_like 'correctly sorted packages list', 'Created' do + it_behaves_like 'correctly sorted packages list', 'Published' do let(:packages) { [package_two, package_one] } end - it_behaves_like 'correctly sorted packages list', 'Created', ascending: true do + it_behaves_like 'correctly sorted packages list', 'Published', ascending: true do let(:packages) { [package_one, package_two] } end end diff --git a/spec/support/shared_examples/features/page_description_shared_examples.rb b/spec/support/shared_examples/features/page_description_shared_examples.rb new file mode 100644 index 00000000000..81653220b4c --- /dev/null +++ b/spec/support/shared_examples/features/page_description_shared_examples.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'page meta description' do |expected_description| + it 'renders the page with description, og:description, and twitter:description meta tags that contains a plain-text version of the markdown', :aggregate_failures do + %w(name='description' property='og:description' property='twitter:description').each do |selector| + expect(page).to have_selector("meta[#{selector}][content='#{expected_description}']", visible: false) + end + end +end diff --git a/spec/support/shared_examples/features/protected_branches_with_deploy_keys_examples.rb b/spec/support/shared_examples/features/protected_branches_with_deploy_keys_examples.rb new file mode 100644 index 00000000000..a2d2143271c --- /dev/null +++ b/spec/support/shared_examples/features/protected_branches_with_deploy_keys_examples.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'when the deploy_keys_on_protected_branches FF is turned on' do + before do + stub_feature_flags(deploy_keys_on_protected_branches: true) + project.add_maintainer(user) + sign_in(user) + end + + let(:dropdown_sections_minus_deploy_keys) { all_dropdown_sections - ['Deploy Keys'] } + + context 'when deploy keys are enabled to this project' do + let!(:deploy_key_1) { create(:deploy_key, title: 'title 1', projects: [project]) } + let!(:deploy_key_2) { create(:deploy_key, title: 'title 2', projects: [project]) } + + context 'when only one deploy key can push' do + before do + deploy_key_1.deploy_keys_projects.first.update!(can_push: true) + end + + it "shows all dropdown sections in the 'Allowed to push' main dropdown, with only one deploy key" do + visit project_protected_branches_path(project) + + find(".js-allowed-to-push").click + wait_for_requests + + within('.qa-allowed-to-push-dropdown') do + dropdown_headers = page.all('.dropdown-header').map(&:text) + + expect(dropdown_headers).to contain_exactly(*all_dropdown_sections) + expect(page).to have_content('title 1') + expect(page).not_to have_content('title 2') + end + end + + it "shows all sections but not deploy keys in the 'Allowed to merge' main dropdown" do + visit project_protected_branches_path(project) + + find(".js-allowed-to-merge").click + wait_for_requests + + within('.qa-allowed-to-merge-dropdown') do + dropdown_headers = page.all('.dropdown-header').map(&:text) + + expect(dropdown_headers).to contain_exactly(*dropdown_sections_minus_deploy_keys) + end + end + + it "shows all sections in the 'Allowed to push' update dropdown" do + create(:protected_branch, :no_one_can_push, project: project, name: 'master') + + visit project_protected_branches_path(project) + + within(".js-protected-branch-edit-form") do + find(".js-allowed-to-push").click + wait_for_requests + + dropdown_headers = page.all('.dropdown-header').map(&:text) + + expect(dropdown_headers).to contain_exactly(*all_dropdown_sections) + end + end + end + + context 'when no deploy key can push' do + it "just shows all sections but not deploy keys in the 'Allowed to push' dropdown" do + visit project_protected_branches_path(project) + + find(".js-allowed-to-push").click + wait_for_requests + + within('.qa-allowed-to-push-dropdown') do + dropdown_headers = page.all('.dropdown-header').map(&:text) + + expect(dropdown_headers).to contain_exactly(*dropdown_sections_minus_deploy_keys) + end + end + + it "just shows all sections but not deploy keys in the 'Allowed to push' update dropdown" do + create(:protected_branch, :no_one_can_push, project: project, name: 'master') + + visit project_protected_branches_path(project) + + within(".js-protected-branch-edit-form") do + find(".js-allowed-to-push").click + wait_for_requests + + dropdown_headers = page.all('.dropdown-header').map(&:text) + + expect(dropdown_headers).to contain_exactly(*dropdown_sections_minus_deploy_keys) + end + end + end + end +end diff --git a/spec/support/shared_examples/features/snippets_shared_examples.rb b/spec/support/shared_examples/features/snippets_shared_examples.rb index 8d68b1e4c0a..bd1a67f3bb5 100644 --- a/spec/support/shared_examples/features/snippets_shared_examples.rb +++ b/spec/support/shared_examples/features/snippets_shared_examples.rb @@ -84,7 +84,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do expect(page).not_to have_selector('.js-blob-viewer-switcher') # shows an enabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + expect(page).to have_button('Copy file contents', disabled: false) # shows a raw button expect(page).to have_link('Open raw') @@ -106,7 +106,6 @@ RSpec.shared_examples 'show and render proper snippet blob' do it 'displays the blob using the rich viewer' do aggregate_failures do # hides the simple viewer - expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false) expect(page).to have_selector('.blob-viewer[data-type="rich"]') # shows rendered Markdown @@ -116,7 +115,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do expect(page).to have_selector('.js-blob-viewer-switcher') # shows a disabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn.disabled') + expect(page).to have_button('Copy file contents', disabled: true) # shows a raw button expect(page).to have_link('Open raw') @@ -128,7 +127,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do context 'switching to the simple viewer' do before do - find('.js-blob-viewer-switch-btn[data-viewer=simple]').click + find_button('Display source').click wait_for_requests end @@ -137,19 +136,18 @@ RSpec.shared_examples 'show and render proper snippet blob' do aggregate_failures do # hides the rich viewer expect(page).to have_selector('.blob-viewer[data-type="simple"]') - expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false) # shows highlighted Markdown code expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)") # shows an enabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + expect(page).to have_button('Copy file contents', disabled: false) end end context 'switching to the rich viewer again' do before do - find('.js-blob-viewer-switch-btn[data-viewer=rich]').click + find_button('Display rendered file').click wait_for_requests end @@ -157,11 +155,11 @@ RSpec.shared_examples 'show and render proper snippet blob' do it 'displays the blob using the rich viewer' do aggregate_failures do # hides the simple viewer - expect(page).to have_selector('.blob-viewer[data-type="simple"]', visible: false) expect(page).to have_selector('.blob-viewer[data-type="rich"]') - # shows an enabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + # Used to show an enabled copy button since the code has already been fetched + # Will be resolved in https://gitlab.com/gitlab-org/gitlab/-/issues/262389 + expect(page).to have_button('Copy file contents', disabled: true) end end end @@ -169,7 +167,8 @@ RSpec.shared_examples 'show and render proper snippet blob' do end context 'visiting with a line number anchor' do - let(:anchor) { 'L1' } + # L1 used to work and will be revisited in https://gitlab.com/gitlab-org/gitlab/-/issues/262391 + let(:anchor) { 'LC1' } it 'displays the blob using the simple viewer' do subject @@ -177,7 +176,6 @@ RSpec.shared_examples 'show and render proper snippet blob' do aggregate_failures do # hides the rich viewer expect(page).to have_selector('.blob-viewer[data-type="simple"]') - expect(page).to have_selector('.blob-viewer[data-type="rich"]', visible: false) # highlights the line in question expect(page).to have_selector('#LC1.hll') @@ -186,7 +184,7 @@ RSpec.shared_examples 'show and render proper snippet blob' do expect(page).to have_content("[PEP-8](http://www.python.org/dev/peps/pep-0008/)") # shows an enabled copy button - expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') + expect(page).to have_button('Copy file contents', disabled: false) end end end 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 index d30e8241da0..0ef1ccdfe57 100644 --- a/spec/support/shared_examples/features/wiki_file_attachments_shared_examples.rb +++ b/spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb @@ -1,14 +1,12 @@ # frozen_string_literal: true # Requires a context containing: -# project +# wiki RSpec.shared_examples 'wiki file attachments' do include DropzoneHelper context 'uploading attachments', :js do - let(:wiki) { project.wiki } - def attach_with_dropzone(wait = false) dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, wait) 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..a22d98f20c4 --- /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('[data-testid="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..1a5f8d7d8df --- /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('[data-testid="wiki_page_title"]')).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..85eedbf4cc5 --- /dev/null +++ b/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb @@ -0,0 +1,274 @@ +# 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('[data-testid="wiki_page_title"]')).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('[data-testid="wiki_edit_button"]') + + 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('[data-testid="wiki_edit_button"]') + end + + context 'show the diff' do + 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('[data-testid="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_selector('[data-testid="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('[data-testid="wiki_edit_button"]') + 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 |