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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
commit43a25d93ebdabea52f99b05e15b06250cd8f07d7 (patch)
treedceebdc68925362117480a5d672bcff122fb625b /spec/support/shared_examples/features
parent20c84b99005abd1c82101dfeff264ac50d2df211 (diff)
Add latest changes from gitlab-org/gitlab@16-0-stable-eev16.0.0-rc42
Diffstat (limited to 'spec/support/shared_examples/features')
-rw-r--r--spec/support/shared_examples/features/2fa_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/features/abuse_report_shared_examples.rb18
-rw-r--r--spec/support/shared_examples/features/access_tokens_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/confidential_notes_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/content_editor_shared_examples.rb415
-rw-r--r--spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/features/dashboard/sidebar_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/features/deploy_token_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/features/editable_merge_request_shared_examples.rb16
-rw-r--r--spec/support/shared_examples/features/explore/sidebar_shared_examples.rb28
-rw-r--r--spec/support/shared_examples/features/incident_details_routing_shared_examples.rb14
-rw-r--r--spec/support/shared_examples/features/integrations/user_activates_mattermost_slash_command_integration_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/features/manage_applications_shared_examples.rb93
-rw-r--r--spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb2
-rw-r--r--spec/support/shared_examples/features/milestone_editing_shared_examples.rb21
-rw-r--r--spec/support/shared_examples/features/packages_shared_examples.rb69
-rw-r--r--spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb105
-rw-r--r--spec/support/shared_examples/features/protected_tags_with_deploy_keys_examples.rb61
-rw-r--r--spec/support/shared_examples/features/reportable_note_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/features/rss_shared_examples.rb14
-rw-r--r--spec/support/shared_examples/features/runners_shared_examples.rb45
-rw-r--r--spec/support/shared_examples/features/search/redacted_search_results_shared_examples.rb202
-rw-r--r--spec/support/shared_examples/features/secure_oauth_authorizations_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/trial_email_validation_shared_example.rb67
-rw-r--r--spec/support/shared_examples/features/variable_list_pagination_shared_examples.rb66
-rw-r--r--spec/support/shared_examples/features/variable_list_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/features/wiki/file_attachments_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/wiki/user_previews_wiki_changes_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb1
-rw-r--r--spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/features/wiki/user_views_wiki_sidebar_shared_examples.rb38
-rw-r--r--spec/support/shared_examples/features/work_items_shared_examples.rb265
33 files changed, 1200 insertions, 417 deletions
diff --git a/spec/support/shared_examples/features/2fa_shared_examples.rb b/spec/support/shared_examples/features/2fa_shared_examples.rb
index 44f30c32472..6c4e98c9989 100644
--- a/spec/support/shared_examples/features/2fa_shared_examples.rb
+++ b/spec/support/shared_examples/features/2fa_shared_examples.rb
@@ -1,13 +1,11 @@
# frozen_string_literal: true
RSpec.shared_examples 'hardware device for 2fa' do |device_type|
- include Spec::Support::Helpers::Features::TwoFactorHelpers
+ include Features::TwoFactorHelpers
include Spec::Support::Helpers::ModalHelpers
def register_device(device_type, **kwargs)
case device_type.downcase
- when "u2f"
- register_u2f_device(**kwargs)
when "webauthn"
register_webauthn_device(**kwargs)
else
@@ -98,9 +96,7 @@ RSpec.shared_examples 'hardware device for 2fa' do |device_type|
end
it 'provides a button that shows the fallback otp code UI' do
- expect(page).to have_link('Sign in via 2FA code')
-
- click_link('Sign in via 2FA code')
+ click_button(_('Sign in via 2FA code'))
assert_fallback_ui(page)
end
diff --git a/spec/support/shared_examples/features/abuse_report_shared_examples.rb b/spec/support/shared_examples/features/abuse_report_shared_examples.rb
new file mode 100644
index 00000000000..ea9b4e9f4b2
--- /dev/null
+++ b/spec/support/shared_examples/features/abuse_report_shared_examples.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'reports the user with an abuse category' do
+ it 'creates abuse report' do
+ click_button 'Report abuse'
+ choose "They're posting spam."
+ click_button 'Next'
+
+ page.attach_file('spec/fixtures/dk.png') do
+ click_button "Choose file"
+ end
+
+ fill_in 'abuse_report_message', with: 'This user sends spam'
+ click_button 'Send report'
+
+ expect(page).to have_content 'Thank you for your report'
+ end
+end
diff --git a/spec/support/shared_examples/features/access_tokens_shared_examples.rb b/spec/support/shared_examples/features/access_tokens_shared_examples.rb
index 32a7b32ac72..3c78869ffaa 100644
--- a/spec/support/shared_examples/features/access_tokens_shared_examples.rb
+++ b/spec/support/shared_examples/features/access_tokens_shared_examples.rb
@@ -9,7 +9,7 @@ RSpec.shared_examples 'resource access tokens missing access rights' do
end
RSpec.shared_examples 'resource access tokens creation' do |resource_type|
- include Spec::Support::Helpers::AccessTokenHelpers
+ include Features::AccessTokenHelpers
it 'allows creation of an access token', :aggregate_failures do
name = 'My access token'
diff --git a/spec/support/shared_examples/features/confidential_notes_shared_examples.rb b/spec/support/shared_examples/features/confidential_notes_shared_examples.rb
index 289da025af6..cd0e8f94934 100644
--- a/spec/support/shared_examples/features/confidential_notes_shared_examples.rb
+++ b/spec/support/shared_examples/features/confidential_notes_shared_examples.rb
@@ -3,7 +3,7 @@
require "spec_helper"
RSpec.shared_examples 'confidential notes on issuables' do
- include Spec::Support::Helpers::Features::NotesHelpers
+ include Features::NotesHelpers
context 'when user does not have permissions' do
it 'does not show confidential note checkbox' do
diff --git a/spec/support/shared_examples/features/content_editor_shared_examples.rb b/spec/support/shared_examples/features/content_editor_shared_examples.rb
index 6cd9c4ce1c4..41114197ff5 100644
--- a/spec/support/shared_examples/features/content_editor_shared_examples.rb
+++ b/spec/support/shared_examples/features/content_editor_shared_examples.rb
@@ -1,116 +1,310 @@
# frozen_string_literal: true
+require 'spec_helper'
+
RSpec.shared_examples 'edits content using the content editor' do
+ include ContentEditorHelpers
+
let(:content_editor_testid) { '[data-testid="content-editor"] [contenteditable].ProseMirror' }
- def switch_to_content_editor
- click_button _('View rich text')
- click_button _('Rich text')
- end
+ let(:is_mac) { page.evaluate_script('navigator.platform').include?('Mac') }
+ let(:modifier_key) { is_mac ? :command : :control }
- def type_in_content_editor(keys)
- find(content_editor_testid).send_keys keys
- end
+ it 'saves page content in local storage if the user navigates away' do
+ switch_to_content_editor
- def open_insert_media_dropdown
- page.find('svg[data-testid="media-icon"]').click
- end
+ expect(page).to have_css(content_editor_testid)
- def set_source_editor_content(content)
- find('.js-gfm-input').set content
- end
+ type_in_content_editor ' Typing text in the content editor'
- def expect_formatting_menu_to_be_visible
- expect(page).to have_css('[data-testid="formatting-bubble-menu"]')
- end
+ wait_until_hidden_field_is_updated /Typing text in the content editor/
- def expect_formatting_menu_to_be_hidden
- expect(page).not_to have_css('[data-testid="formatting-bubble-menu"]')
- end
+ begin
+ refresh
+ rescue Selenium::WebDriver::Error::UnexpectedAlertOpenError
+ end
- def expect_media_bubble_menu_to_be_visible
- expect(page).to have_css('[data-testid="media-bubble-menu"]')
+ expect(page).to have_text('Typing text in the content editor')
end
- def upload_asset(fixture_name)
- attach_file('content_editor_image', Rails.root.join('spec', 'fixtures', fixture_name), make_visible: true)
- end
+ describe 'creating and editing links' do
+ before do
+ switch_to_content_editor
+ end
- def wait_until_hidden_field_is_updated(value)
- expect(page).to have_field('wiki[content]', with: value, type: 'hidden')
- end
+ context 'when clicking the link icon in the toolbar' do
+ it 'shows the link bubble menu' do
+ page.find('[data-testid="formatting-toolbar"] [data-testid="link"]').click
- it 'saves page content in local storage if the user navigates away' do
- switch_to_content_editor
+ expect(page).to have_css('[data-testid="link-bubble-menu"]')
+ end
- expect(page).to have_css(content_editor_testid)
+ context 'if no text is selected' do
+ before do
+ page.find('[data-testid="formatting-toolbar"] [data-testid="link"]').click
+ end
+
+ it 'opens an empty inline modal to create a link' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ expect(page).to have_field('link-text', with: '')
+ expect(page).to have_field('link-href', with: '')
+ end
+ end
+
+ context 'when the user clicks the apply button' do
+ it 'applies the changes to the document' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ fill_in 'link-text', with: 'Link to GitLab home page'
+ fill_in 'link-href', with: 'https://gitlab.com'
+
+ click_button 'Apply'
+ end
+
+ page.within content_editor_testid do
+ expect(page).to have_css('a[href="https://gitlab.com"]')
+ expect(page).to have_text('Link to GitLab home page')
+ end
+ end
+ end
+
+ context 'when the user clicks the cancel button' do
+ it 'does not apply the changes to the document' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ fill_in 'link-text', with: 'Link to GitLab home page'
+ fill_in 'link-href', with: 'https://gitlab.com'
+
+ click_button 'Cancel'
+ end
+
+ page.within content_editor_testid do
+ expect(page).not_to have_css('a')
+ end
+ end
+ end
+ end
- type_in_content_editor ' Typing text in the content editor'
+ context 'if text is selected' do
+ before do
+ type_in_content_editor 'The quick brown fox jumps over the lazy dog'
+ type_in_content_editor [:shift, :left]
+ type_in_content_editor [:shift, :left]
+ type_in_content_editor [:shift, :left]
+
+ page.find('[data-testid="formatting-toolbar"] [data-testid="link"]').click
+ end
+
+ it 'prefills inline modal to create a link' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ expect(page).to have_field('link-text', with: 'dog')
+ expect(page).to have_field('link-href', with: '')
+ end
+ end
+
+ context 'when the user clicks the apply button' do
+ it 'applies the changes to the document' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ fill_in 'link-text', with: 'new dog'
+ fill_in 'link-href', with: 'https://en.wikipedia.org/wiki/Shiba_Inu'
+
+ click_button 'Apply'
+ end
+
+ page.within content_editor_testid do
+ expect(page).to have_selector('a[href="https://en.wikipedia.org/wiki/Shiba_Inu"]',
+ text: 'new dog'
+ )
+ end
+ end
+ end
+ end
+ end
- wait_until_hidden_field_is_updated /Typing text in the content editor/
+ context 'if cursor is placed on an existing link' do
+ before do
+ type_in_content_editor 'Link to [GitLab home **page**](https://gitlab.com)'
+ type_in_content_editor :left
+ end
- refresh
+ it 'prefills inline modal to edit the link' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ page.find('[data-testid="edit-link"]').click
- expect(page).to have_text('Typing text in the content editor')
+ expect(page).to have_field('link-text', with: 'GitLab home page')
+ expect(page).to have_field('link-href', with: 'https://gitlab.com')
+ end
+ end
- refresh # also retained after second refresh
+ it 'updates the link attributes if text is not updated' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ page.find('[data-testid="edit-link"]').click
- expect(page).to have_text('Typing text in the content editor')
+ fill_in 'link-href', with: 'https://about.gitlab.com'
- click_link 'Cancel' # draft is deleted on cancel
+ click_button 'Apply'
+ end
- page.go_back
+ page.within content_editor_testid do
+ expect(page).to have_selector('a[href="https://about.gitlab.com"]')
+ expect(page.find('a')).to have_text('GitLab home page')
+ expect(page).to have_selector('strong', text: 'page')
+ end
+ end
- expect(page).not_to have_text('Typing text in the content editor')
- end
+ it 'updates the link attributes and text if text is updated' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ page.find('[data-testid="edit-link"]').click
- describe 'formatting bubble menu' do
- it 'shows a formatting bubble menu for a regular paragraph and headings' do
- switch_to_content_editor
+ fill_in 'link-text', with: 'GitLab about page'
+ fill_in 'link-href', with: 'https://about.gitlab.com'
- expect(page).to have_css(content_editor_testid)
+ click_button 'Apply'
+ end
- type_in_content_editor 'Typing text in the content editor'
- type_in_content_editor [:shift, :left]
+ page.within content_editor_testid do
+ expect(page).to have_selector('a[href="https://about.gitlab.com"]',
+ text: 'GitLab about page'
+ )
+ expect(page).not_to have_selector('strong')
+ end
+ end
- expect_formatting_menu_to_be_visible
+ it 'does nothing if Cancel is clicked' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ page.find('[data-testid="edit-link"]').click
- type_in_content_editor [:right, :right, :enter, '## Heading']
+ click_button 'Cancel'
+ end
- expect_formatting_menu_to_be_hidden
+ page.within content_editor_testid do
+ expect(page).to have_selector('a[href="https://gitlab.com"]',
+ text: 'GitLab home page'
+ )
+ expect(page).to have_selector('strong')
+ end
+ end
- type_in_content_editor [:shift, :left]
+ context 'when the user clicks the unlink button' do
+ it 'removes the link' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ page.find('[data-testid="remove-link"]').click
+ end
+
+ page.within content_editor_testid do
+ expect(page).not_to have_selector('a')
+ expect(page).to have_selector('strong', text: 'page')
+ end
+ end
+ end
+ end
+
+ context 'when selection spans more than a link' do
+ before do
+ type_in_content_editor 'a [b **c**](https://gitlab.com)'
+
+ type_in_content_editor [:shift, :left]
+ type_in_content_editor [:shift, :left]
+ type_in_content_editor [:shift, :left]
+ type_in_content_editor [:shift, :left]
+ type_in_content_editor [:shift, :left]
+
+ page.find('[data-testid="formatting-toolbar"] [data-testid="link"]').click
+ end
+
+ it 'prefills inline modal with the entire selection' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ expect(page).to have_field('link-text', with: 'a b c')
+ expect(page).to have_field('link-href', with: '')
+ end
+ end
- expect_formatting_menu_to_be_visible
+ it 'expands the link and updates the link attributes if text is not updated' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ fill_in 'link-href', with: 'https://about.gitlab.com'
+
+ click_button 'Apply'
+ end
+
+ page.within content_editor_testid do
+ expect(page).to have_selector('a[href="https://about.gitlab.com"]')
+ expect(page.find('a')).to have_text('a b c')
+ expect(page).to have_selector('strong', text: 'c')
+ end
+ end
+
+ it 'expands the link, updates the link attributes and text if text is updated' do
+ page.within '[data-testid="link-bubble-menu"]' do
+ fill_in 'link-text', with: 'new text'
+ fill_in 'link-href', with: 'https://about.gitlab.com'
+
+ click_button 'Apply'
+ end
+
+ page.within content_editor_testid do
+ expect(page).to have_selector('a[href="https://about.gitlab.com"]',
+ text: 'new text'
+ )
+ expect(page).not_to have_selector('strong')
+ end
+ end
end
end
- describe 'media elements bubble menu' do
+ describe 'selecting text' do
before do
switch_to_content_editor
- open_insert_media_dropdown
+ # delete all text first
+ type_in_content_editor [modifier_key, 'a']
+ type_in_content_editor :backspace
+
+ type_in_content_editor 'The quick **brown** fox _jumps_ over the lazy dog!'
+ type_in_content_editor :enter
+ type_in_content_editor '[Link](https://gitlab.com)'
+ type_in_content_editor :enter
+ type_in_content_editor 'Jackdaws love my ~~big~~ sphinx of quartz!'
+
+ # select all text
+ type_in_content_editor [modifier_key, 'a']
end
- def test_displays_media_bubble_menu(media_element_selector, fixture_file)
- upload_asset fixture_file
+ it 'renders selected text in a .content-editor-selection class' do
+ page.within content_editor_testid do
+ assert_selected 'The quick'
+ assert_selected 'brown'
+ assert_selected 'fox'
+ assert_selected 'jumps'
+ assert_selected 'over the lazy dog!'
- wait_for_requests
+ assert_selected 'Link'
- expect(page).to have_css(media_element_selector)
+ assert_selected 'Jackdaws love my'
+ assert_selected 'big'
+ assert_selected 'sphinx of quartz!'
+ end
+ end
- page.find(media_element_selector).click
+ def assert_selected(text)
+ expect(page).to have_selector('.content-editor-selection', text: text)
+ end
+ end
- expect_formatting_menu_to_be_hidden
- expect_media_bubble_menu_to_be_visible
+ describe 'media elements bubble menu' do
+ before do
+ switch_to_content_editor
+
+ click_attachment_button
end
it 'displays correct media bubble menu for images', :js do
- test_displays_media_bubble_menu '[data-testid="content_editor_editablebox"] img[src]', 'dk.png'
+ display_media_bubble_menu '[data-testid="content_editor_editablebox"] img[src]', 'dk.png'
+
+ expect_media_bubble_menu_to_be_visible
end
it 'displays correct media bubble menu for video', :js do
- test_displays_media_bubble_menu '[data-testid="content_editor_editablebox"] video', 'video_sample.mp4'
+ display_media_bubble_menu '[data-testid="content_editor_editablebox"] video', 'video_sample.mp4'
+
+ expect_media_bubble_menu_to_be_visible
end
end
@@ -150,7 +344,6 @@ RSpec.shared_examples 'edits content using the content editor' do
type_in_content_editor 'var a = 0'
type_in_content_editor [:shift, :left]
- expect_formatting_menu_to_be_hidden
expect(page).to have_css('[data-testid="code-block-bubble-menu"]')
end
@@ -187,8 +380,8 @@ RSpec.shared_examples 'edits content using the content editor' do
expect(iframe['src']).to include('/-/sandbox/mermaid')
within_frame(iframe) do
- expect(find('svg').text).to include('JohnDoe12')
- expect(find('svg').text).to include('HelloWorld34')
+ expect(find('svg .nodes').text).to include('JohnDoe12')
+ expect(find('svg .nodes').text).to include('HelloWorld34')
end
expect(iframe['height'].to_i).to be > 100
@@ -198,12 +391,13 @@ RSpec.shared_examples 'edits content using the content editor' do
within_frame(iframe) do
page.has_content?('JaneDoe34')
- expect(find('svg').text).to include('JaneDoe34')
- expect(find('svg').text).to include('HelloWorld56')
+ expect(find('svg .nodes').text).to include('JaneDoe34')
+ expect(find('svg .nodes').text).to include('HelloWorld56')
end
end
- it 'toggles the diagram when preview button is clicked' do
+ it 'toggles the diagram when preview button is clicked',
+ quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/397682' do
find('[data-testid="preview-diagram"]').click
expect(find(content_editor_testid)).not_to have_selector('iframe')
@@ -213,8 +407,61 @@ RSpec.shared_examples 'edits content using the content editor' do
iframe = find(content_editor_testid).find('iframe')
within_frame(iframe) do
- expect(find('svg').text).to include('JohnDoe12')
- expect(find('svg').text).to include('HelloWorld34')
+ expect(find('svg .nodes').text).to include('JohnDoe12')
+ expect(find('svg .nodes').text).to include('HelloWorld34')
+ end
+ end
+ end
+
+ describe 'pasting text' do
+ before do
+ switch_to_content_editor
+
+ type_in_content_editor "Some **rich** _text_ ~~content~~ [link](https://gitlab.com)"
+
+ type_in_content_editor [modifier_key, 'a']
+ type_in_content_editor [modifier_key, 'x']
+ end
+
+ it 'pastes text with formatting if ctrl + v is pressed' do
+ type_in_content_editor [modifier_key, 'v']
+
+ page.within content_editor_testid do
+ expect(page).to have_selector('strong', text: 'rich')
+ expect(page).to have_selector('em', text: 'text')
+ expect(page).to have_selector('s', text: 'content')
+ expect(page).to have_selector('a[href="https://gitlab.com"]', text: 'link')
+ end
+ end
+
+ it 'pastes raw text without formatting if shift + ctrl + v is pressed' do
+ type_in_content_editor [modifier_key, :shift, 'v']
+
+ page.within content_editor_testid do
+ expect(page).to have_text('Some rich text content link')
+
+ expect(page).not_to have_selector('strong')
+ expect(page).not_to have_selector('em')
+ expect(page).not_to have_selector('s')
+ expect(page).not_to have_selector('a')
+ end
+ end
+
+ it 'pastes raw text without formatting, stripping whitespaces, if shift + ctrl + v is pressed' do
+ type_in_content_editor " Some **rich**"
+ type_in_content_editor :enter
+ type_in_content_editor " _text_"
+ type_in_content_editor :enter
+ type_in_content_editor " ~~content~~"
+ type_in_content_editor :enter
+ type_in_content_editor " [link](https://gitlab.com)"
+
+ type_in_content_editor [modifier_key, 'a']
+ type_in_content_editor [modifier_key, 'x']
+ type_in_content_editor [modifier_key, :shift, 'v']
+
+ page.within content_editor_testid do
+ expect(page).to have_text('Some rich text content link')
end
end
end
@@ -225,7 +472,7 @@ RSpec.shared_examples 'edits content using the content editor' do
before do
if defined?(project)
create(:issue, project: project, title: 'My Cool Linked Issue')
- create(:merge_request, source_project: project, title: 'My Cool Merge Request')
+ create(:merge_request, source_project: project, source_branch: 'branch-1', title: 'My Cool Merge Request')
create(:label, project: project, title: 'My Cool Label')
create(:milestone, project: project, title: 'My Cool Milestone')
@@ -234,7 +481,7 @@ RSpec.shared_examples 'edits content using the content editor' do
project = create(:project, group: group)
create(:issue, project: project, title: 'My Cool Linked Issue')
- create(:merge_request, source_project: project, title: 'My Cool Merge Request')
+ create(:merge_request, source_project: project, source_branch: 'branch-1', title: 'My Cool Merge Request')
create(:group_label, group: group, title: 'My Cool Label')
create(:milestone, group: group, title: 'My Cool Milestone')
@@ -251,7 +498,9 @@ RSpec.shared_examples 'edits content using the content editor' do
expect(find(suggestions_dropdown)).to have_text('abc123')
expect(find(suggestions_dropdown)).to have_text('all')
- expect(find(suggestions_dropdown)).to have_text('Group Members (2)')
+ expect(find(suggestions_dropdown)).to have_text('Group Members')
+
+ type_in_content_editor 'bc'
send_keys [:arrow_down, :enter]
@@ -332,3 +581,23 @@ RSpec.shared_examples 'edits content using the content editor' do
end
end
end
+
+RSpec.shared_examples 'inserts diagrams.net diagram using the content editor' do
+ include ContentEditorHelpers
+
+ before do
+ switch_to_content_editor
+
+ click_attachment_button
+ end
+
+ it 'displays correct media bubble menu with edit diagram button' do
+ display_media_bubble_menu '[data-testid="content_editor_editablebox"] img[src]', 'diagram.drawio.svg'
+
+ expect_media_bubble_menu_to_be_visible
+
+ click_edit_diagram_button
+
+ expect_drawio_editor_is_opened
+ end
+end
diff --git a/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb b/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb
index 96e57980c68..7e0e235698e 100644
--- a/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb
+++ b/spec/support/shared_examples/features/creatable_merge_request_shared_examples.rb
@@ -5,20 +5,20 @@ RSpec.shared_examples 'a creatable merge request' do
include ListboxHelpers
it 'creates new merge request', :js do
- find('.js-assignee-search').click
+ find('[data-testid="assignee-ids-dropdown-toggle"]').click
page.within '.dropdown-menu-user' do
click_link user2.name
end
expect(find('input[name="merge_request[assignee_ids][]"]', visible: false).value).to match(user2.id.to_s)
- page.within '.js-assignee-search' do
+ page.within '[data-testid="assignee-ids-dropdown-toggle"]' do
expect(page).to have_content user2.name
end
click_link 'Assign to me'
expect(find('input[name="merge_request[assignee_ids][]"]', visible: false).value).to match(user.id.to_s)
- page.within '.js-assignee-search' do
+ page.within '[data-testid="assignee-ids-dropdown-toggle"]' do
expect(page).to have_content user.name
end
diff --git a/spec/support/shared_examples/features/dashboard/sidebar_shared_examples.rb b/spec/support/shared_examples/features/dashboard/sidebar_shared_examples.rb
index efbd735c451..9b5d9d66890 100644
--- a/spec/support/shared_examples/features/dashboard/sidebar_shared_examples.rb
+++ b/spec/support/shared_examples/features/dashboard/sidebar_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples "a dashboard page with sidebar" do |page_path, menu_label|
+RSpec.shared_examples 'a "Your work" page with sidebar and breadcrumbs' do |page_path, menu_label|
before do
sign_in(user)
visit send(page_path)
@@ -18,4 +18,13 @@ RSpec.shared_examples "a dashboard page with sidebar" do |page_path, menu_label|
expect(page).to have_css(active_menu_item_css)
end
end
+
+ describe "breadcrumbs" do
+ it 'has "Your work" as its root breadcrumb' do
+ breadcrumbs = page.find('[data-testid="breadcrumb-links"]')
+ within breadcrumbs do
+ expect(page).to have_css("li:first-child a[href=\"#{root_path}\"]", text: "Your work")
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/features/deploy_token_shared_examples.rb b/spec/support/shared_examples/features/deploy_token_shared_examples.rb
index 9fe08e5c996..80f5f1d805c 100644
--- a/spec/support/shared_examples/features/deploy_token_shared_examples.rb
+++ b/spec/support/shared_examples/features/deploy_token_shared_examples.rb
@@ -17,9 +17,11 @@ RSpec.shared_examples 'a deploy token in settings' do
it 'add a new deploy token', :js do
visit page_path
- fill_in _('Name'), with: 'new_deploy_key'
- fill_in _('Expiration date (optional)'), with: (Date.today + 1.month).to_s
- fill_in _('Username (optional)'), with: 'deployer'
+ within('#js-deploy-tokens') do
+ fill_in _('Name'), with: 'new_deploy_key'
+ fill_in _('Expiration date (optional)'), with: (Date.today + 1.month).to_s
+ fill_in _('Username (optional)'), with: 'deployer'
+ end
check 'read_repository'
check 'read_registry'
click_button 'Create deploy token'
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 ea6d1655694..14e53dc8655 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
@@ -77,15 +77,21 @@ RSpec.shared_examples 'an editable merge request' do
expect(page).to have_selector('.js-quick-submit')
end
- it 'warns about version conflict' do
+ it 'warns about version conflict', :js do
merge_request.update!(title: "New title")
fill_in 'merge_request_title', with: 'bug 345'
fill_in 'merge_request_description', with: 'bug description'
- click_button 'Save changes'
+ click_button _('Save changes')
- expect(page).to have_content 'Someone edited the merge request the same time you did'
+ expect(page).to have_content(
+ format(
+ _("Someone edited this %{model_name} at the same time you did. Please check out the %{link_to_model} and make sure your changes will not unintentionally remove theirs."), # rubocop:disable Layout/LineLength
+ model_name: _('merge request'),
+ link_to_model: _('merge request')
+ )
+ )
end
it 'preserves description textarea height', :js do
@@ -104,8 +110,8 @@ RSpec.shared_examples 'an editable merge request' do
fill_in 'merge_request_description', with: long_description
height = get_textarea_height
- find('.js-md-preview-button').click
- find('.js-md-write-button').click
+ click_button("Preview")
+ click_button("Continue editing")
new_height = get_textarea_height
expect(height).to eq(new_height)
diff --git a/spec/support/shared_examples/features/explore/sidebar_shared_examples.rb b/spec/support/shared_examples/features/explore/sidebar_shared_examples.rb
new file mode 100644
index 00000000000..1754c8bf53d
--- /dev/null
+++ b/spec/support/shared_examples/features/explore/sidebar_shared_examples.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'an "Explore" page with sidebar and breadcrumbs' do |page_path, menu_label|
+ before do
+ visit send(page_path)
+ end
+
+ let(:sidebar_css) { 'aside.nav-sidebar[aria-label="Explore"]' }
+ let(:active_menu_item_css) { "li.active[data-track-label=\"#{menu_label}_menu\"]" }
+
+ it 'shows the "Explore" sidebar' do
+ expect(page).to have_css(sidebar_css)
+ end
+
+ it 'shows the correct sidebar menu item as active' do
+ within(sidebar_css) do
+ expect(page).to have_css(active_menu_item_css)
+ end
+ end
+
+ describe 'breadcrumbs' do
+ it 'has "Explore" as its root breadcrumb' do
+ within '.breadcrumbs-list' do
+ expect(page).to have_css("li:first a[href=\"#{explore_root_path}\"]", text: 'Explore')
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/incident_details_routing_shared_examples.rb b/spec/support/shared_examples/features/incident_details_routing_shared_examples.rb
index dab125caa60..b8e42843e6f 100644
--- a/spec/support/shared_examples/features/incident_details_routing_shared_examples.rb
+++ b/spec/support/shared_examples/features/incident_details_routing_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples 'for each incident details route' do |example, tab_text:|
+RSpec.shared_examples 'for each incident details route' do |example, tab_text:, tab:|
before do
sign_in(user)
visit incident_path
@@ -25,4 +25,16 @@ RSpec.shared_examples 'for each incident details route' do |example, tab_text:|
it_behaves_like example
end
+
+ context "for /-/issues/incident/:id/#{tab} route" do
+ let(:incident_path) { incident_project_issues_path(project, incident, tab) }
+
+ it_behaves_like example
+ end
+
+ context "for /-/issues/:id/#{tab} route" do
+ let(:incident_path) { incident_issue_project_issue_path(project, incident, tab) }
+
+ it_behaves_like example
+ end
end
diff --git a/spec/support/shared_examples/features/integrations/user_activates_mattermost_slash_command_integration_shared_examples.rb b/spec/support/shared_examples/features/integrations/user_activates_mattermost_slash_command_integration_shared_examples.rb
index 4c312b42c0a..148ff2cfb54 100644
--- a/spec/support/shared_examples/features/integrations/user_activates_mattermost_slash_command_integration_shared_examples.rb
+++ b/spec/support/shared_examples/features/integrations/user_activates_mattermost_slash_command_integration_shared_examples.rb
@@ -8,7 +8,7 @@ RSpec.shared_examples 'user activates the Mattermost Slash Command integration'
it 'shows a token placeholder' do
token_placeholder = find_field('service_token')['placeholder']
- expect(token_placeholder).to eq('XXxxXXxxXXxxXXxxXXxxXXxx')
+ expect(token_placeholder).to eq('')
end
it 'redirects to the integrations page after saving but not activating' do
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
index b6f7094e422..b8c6b85adb2 100644
--- a/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb
+++ b/spec/support/shared_examples/features/issuable_invite_members_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples 'issuable invite members' do
- include Spec::Support::Helpers::Features::InviteMembersModalHelper
+ include Features::InviteMembersModalHelpers
context 'when a privileged user can invite' do
before do
@@ -17,8 +17,6 @@ RSpec.shared_examples 'issuable invite members' do
page.within '.dropdown-menu-user' do
expect(page).to have_link('Invite Members')
- expect(page).to have_selector('[data-track-action="click_invite_members"]')
- expect(page).to have_selector('[data-track-label="edit_assignee"]')
end
click_link 'Invite Members'
diff --git a/spec/support/shared_examples/features/manage_applications_shared_examples.rb b/spec/support/shared_examples/features/manage_applications_shared_examples.rb
index b59f3f1e27b..b8fd58e7efa 100644
--- a/spec/support/shared_examples/features/manage_applications_shared_examples.rb
+++ b/spec/support/shared_examples/features/manage_applications_shared_examples.rb
@@ -5,87 +5,40 @@ RSpec.shared_examples 'manage applications' do
let_it_be(:application_name_changed) { "#{application_name} changed" }
let_it_be(:application_redirect_uri) { 'https://foo.bar' }
- context 'when hash_oauth_secrets flag set' do
- before do
- stub_feature_flags(hash_oauth_secrets: true)
- end
-
- it 'allows user to manage applications', :js do
- visit new_application_path
+ it 'allows user to manage applications', :js do
+ visit new_application_path
- expect(page).to have_content 'Add new application'
+ expect(page).to have_content 'Add new application'
- fill_in :doorkeeper_application_name, with: application_name
- fill_in :doorkeeper_application_redirect_uri, with: application_redirect_uri
- check :doorkeeper_application_scopes_read_user
- click_on 'Save application'
+ fill_in :doorkeeper_application_name, with: application_name
+ fill_in :doorkeeper_application_redirect_uri, with: application_redirect_uri
+ check :doorkeeper_application_scopes_read_user
+ click_on 'Save application'
- validate_application(application_name, 'Yes')
- expect(page).to have_content _('This is the only time the secret is accessible. Copy the secret and store it securely')
- expect(page).to have_link('Continue', href: index_path)
+ validate_application(application_name, 'Yes')
+ expect(page).to have_content _('This is the only time the secret is accessible. Copy the secret and store it securely')
+ expect(page).to have_link('Continue', href: index_path)
- expect(page).to have_css("button[title=\"Copy secret\"]", text: 'Copy')
+ expect(page).to have_button(_('Copy secret'))
- click_on 'Edit'
+ click_on 'Edit'
- application_name_changed = "#{application_name} changed"
+ application_name_changed = "#{application_name} changed"
- fill_in :doorkeeper_application_name, with: application_name_changed
- uncheck :doorkeeper_application_confidential
- click_on 'Save application'
-
- validate_application(application_name_changed, 'No')
- expect(page).not_to have_link('Continue')
- expect(page).to have_content _('The secret is only available when you first create the application')
-
- visit_applications_path
-
- page.within '.oauth-applications' do
- click_on 'Destroy'
- end
- expect(page.find('.oauth-applications')).not_to have_content 'test_changed'
- end
- end
-
- context 'when hash_oauth_secrets flag not set' do
- before do
- stub_feature_flags(hash_oauth_secrets: false)
- end
-
- it 'allows user to manage applications', :js do
- visit new_application_path
-
- expect(page).to have_content 'Add new application'
-
- fill_in :doorkeeper_application_name, with: application_name
- fill_in :doorkeeper_application_redirect_uri, with: application_redirect_uri
- check :doorkeeper_application_scopes_read_user
- click_on 'Save application'
-
- validate_application(application_name, 'Yes')
- expect(page).to have_link('Continue', href: index_path)
-
- application = Doorkeeper::Application.find_by(name: application_name)
- expect(page).to have_css("button[title=\"Copy secret\"][data-clipboard-text=\"#{application.secret}\"]", text: 'Copy')
-
- click_on 'Edit'
-
- application_name_changed = "#{application_name} changed"
-
- fill_in :doorkeeper_application_name, with: application_name_changed
- uncheck :doorkeeper_application_confidential
- click_on 'Save application'
+ fill_in :doorkeeper_application_name, with: application_name_changed
+ uncheck :doorkeeper_application_confidential
+ click_on 'Save application'
- validate_application(application_name_changed, 'No')
- expect(page).not_to have_link('Continue')
+ validate_application(application_name_changed, 'No')
+ expect(page).not_to have_link('Continue')
+ expect(page).to have_content _('The secret is only available when you create the application or renew the secret.')
- visit_applications_path
+ visit_applications_path
- page.within '.oauth-applications' do
- click_on 'Destroy'
- end
- expect(page.find('.oauth-applications')).not_to have_content 'test_changed'
+ page.within '.oauth-applications' do
+ click_on 'Destroy'
end
+ expect(page.find('.oauth-applications')).not_to have_content 'test_changed'
end
context 'when scopes are blank' do
diff --git a/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb b/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb
index c2dc87b0fb0..6487e6a94c1 100644
--- a/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb
+++ b/spec/support/shared_examples/features/master_manages_access_requests_shared_example.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples 'Maintainer manages access requests' do
- include Spec::Support::Helpers::Features::MembersHelpers
+ include Features::MembersHelpers
let(:user) { create(:user) }
let(:maintainer) { create(:user) }
diff --git a/spec/support/shared_examples/features/milestone_editing_shared_examples.rb b/spec/support/shared_examples/features/milestone_editing_shared_examples.rb
new file mode 100644
index 00000000000..d21bf62ecfa
--- /dev/null
+++ b/spec/support/shared_examples/features/milestone_editing_shared_examples.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'milestone handling version conflicts' do
+ it 'warns about version conflict when milestone has been updated in the background' do
+ # Update the milestone in the background in order to trigger a version conflict
+ milestone.update!(title: "New title")
+
+ fill_in _('Title'), with: 'Title for version conflict'
+ fill_in _('Description'), with: 'Description for version conflict'
+
+ click_button _('Save changes')
+
+ expect(page).to have_content(
+ format(
+ _("Someone edited this %{model_name} at the same time you did. Please check out the %{link_to_model} and make sure your changes will not unintentionally remove theirs."), # rubocop:disable Layout/LineLength
+ model_name: _('milestone'),
+ link_to_model: _('milestone')
+ )
+ )
+ end
+end
diff --git a/spec/support/shared_examples/features/packages_shared_examples.rb b/spec/support/shared_examples/features/packages_shared_examples.rb
index f09cf0613a1..5126e849c2e 100644
--- a/spec/support/shared_examples/features/packages_shared_examples.rb
+++ b/spec/support/shared_examples/features/packages_shared_examples.rb
@@ -9,7 +9,7 @@ RSpec.shared_examples 'packages list' do |check_project_name: false|
expect(package_row).to have_content(pkg.name)
expect(package_row).to have_content(pkg.version)
- expect(package_row).to have_content(pkg.project.name) if check_project_name
+ expect(package_row).to have_content(pkg.project.path) if check_project_name
end
end
@@ -18,7 +18,35 @@ RSpec.shared_examples 'packages list' do |check_project_name: false|
end
end
+RSpec.shared_examples 'pipelines on packages list' do
+ let_it_be(:pipelines) do
+ %w[c83d6e391c22777fca1ed3012fce84f633d7fed0
+ d83d6e391c22777fca1ed3012fce84f633d7fed0].map do |sha|
+ create(:ci_pipeline, project: project, sha: sha)
+ end
+ end
+
+ before do
+ pipelines.each do |pipeline|
+ create(:package_build_info, package: package, pipeline: pipeline)
+ end
+ end
+
+ it 'shows the latest pipeline' do
+ # Test after reload
+ page.evaluate_script 'window.location.reload()'
+
+ wait_for_requests
+
+ expect(page).to have_content('d83d6e39')
+ end
+end
+
RSpec.shared_examples 'package details link' do |property|
+ before do
+ stub_application_setting(npm_package_requests_forwarding: false)
+ end
+
it 'navigates to the correct url' do
page.within(packages_table_selector) do
click_link package.name
@@ -30,6 +58,45 @@ RSpec.shared_examples 'package details link' do |property|
expect(page).to have_content('Installation')
expect(page).to have_content('Registry setup')
+ expect(page).to have_content('Other versions 0')
+ end
+
+ context 'with other versions' do
+ let_it_be(:npm_package1) { create(:npm_package, project: project, name: 'zzz', version: '1.1.0') }
+ let_it_be(:npm_package2) { create(:npm_package, project: project, name: 'zzz', version: '1.2.0') }
+
+ before do
+ page.within(packages_table_selector) do
+ first(:link, package.name).click
+ end
+ end
+
+ it 'shows tab with count' do
+ expect(page).to have_content('Other versions 2')
+ end
+
+ it 'visiting tab shows total on page' do
+ click_link 'Other versions'
+
+ expect(page).to have_content('2 versions')
+ end
+
+ it 'deleting version updates count' do
+ click_link 'Other versions'
+
+ find('[data-testid="delete-dropdown"]', match: :first).click
+ find('[data-testid="action-delete"]', match: :first).click
+ click_button('Permanently delete')
+
+ expect(page).to have_content 'Package deleted successfully'
+
+ expect(page).to have_content('Other versions 1')
+ expect(page).to have_content('1 version')
+
+ expect(page).not_to have_content('1.0.0')
+ expect(page).to have_content('1.1.0')
+ expect(page).to have_content('1.2.0')
+ end
end
end
diff --git a/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb b/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb
index 81d548e000a..2d3f1949716 100644
--- a/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb
+++ b/spec/support/shared_examples/features/protected_branches_access_control_ce_shared_examples.rb
@@ -1,126 +1,67 @@
# frozen_string_literal: true
RSpec.shared_examples "protected branches > access control > CE" do
- ProtectedRefAccess::HUMAN_ACCESS_LEVELS.each do |(access_type_id, access_type_name)|
+ let(:no_one) { ProtectedRef::AccessLevel.humanize(::Gitlab::Access::NO_ACCESS) }
+
+ ProtectedRef::AccessLevel.human_access_levels.each do |(access_type_id, access_type_name)|
it "allows creating protected branches that #{access_type_name} can push to" do
visit project_protected_branches_path(project)
set_protected_branch_name('master')
-
- find(".js-allowed-to-merge").click
- within('[data-testid="allowed-to-merge-dropdown"]') do
- expect(first("li")).to have_content("Roles")
- find(:link, 'No one').click
- end
-
- within('.js-new-protected-branch') do
- allowed_to_push_button = find(".js-allowed-to-push")
-
- unless allowed_to_push_button.text == access_type_name
- allowed_to_push_button.click
- within(".dropdown.show .dropdown-menu") { click_on access_type_name }
- end
- end
-
+ set_allowed_to('merge', no_one)
+ set_allowed_to('push', access_type_name)
click_on_protect
- wait_for_requests
expect(ProtectedBranch.count).to eq(1)
expect(ProtectedBranch.last.push_access_levels.map(&:access_level)).to eq([access_type_id])
end
- it "allows updating protected branches so that #{access_type_name} can push to them" do
+ it "allows creating protected branches that #{access_type_name} can merge to" do
visit project_protected_branches_path(project)
set_protected_branch_name('master')
-
- find(".js-allowed-to-merge").click
- within('[data-testid="allowed-to-merge-dropdown"]') do
- expect(first("li")).to have_content("Roles")
- find(:link, 'No one').click
- end
-
- find(".js-allowed-to-push").click
- within('[data-testid="allowed-to-push-dropdown"]') do
- expect(first("li")).to have_content("Roles")
- find(:link, 'No one').click
- end
-
+ set_allowed_to('merge', access_type_name)
+ set_allowed_to('push', no_one)
click_on_protect
expect(ProtectedBranch.count).to eq(1)
-
- within(".protected-branches-list") do
- find(".js-allowed-to-push").click
-
- within('.js-allowed-to-push-container') do
- expect(first("li")).to have_content("Roles")
- find(:link, access_type_name).click
- end
-
- find(".js-allowed-to-push").click
- end
-
- wait_for_requests
-
- expect(ProtectedBranch.last.push_access_levels.map(&:access_level)).to include(access_type_id)
+ expect(ProtectedBranch.last.merge_access_levels.map(&:access_level)).to eq([access_type_id])
end
- end
- ProtectedRefAccess::HUMAN_ACCESS_LEVELS.each do |(access_type_id, access_type_name)|
- it "allows creating protected branches that #{access_type_name} can merge to" do
+ it "allows updating protected branches so that #{access_type_name} can push to them" do
visit project_protected_branches_path(project)
set_protected_branch_name('master')
+ set_allowed_to('merge', no_one)
+ set_allowed_to('push', no_one)
+ click_on_protect
- within('.js-new-protected-branch') do
- allowed_to_merge_button = find(".js-allowed-to-merge")
+ expect(ProtectedBranch.count).to eq(1)
- unless allowed_to_merge_button.text == access_type_name
- allowed_to_merge_button.click
- within(".dropdown.show .dropdown-menu") { click_on access_type_name }
+ within(".protected-branches-list") do
+ within_select(".js-allowed-to-push") do
+ click_on(access_type_name)
end
end
- find(".js-allowed-to-push").click
- within('[data-testid="allowed-to-push-dropdown"]') do
- expect(first("li")).to have_content("Roles")
- find(:link, 'No one').click
- end
-
- click_on_protect
+ wait_for_requests
- expect(ProtectedBranch.count).to eq(1)
- expect(ProtectedBranch.last.merge_access_levels.map(&:access_level)).to eq([access_type_id])
+ expect(ProtectedBranch.last.push_access_levels.map(&:access_level)).to include(access_type_id)
end
it "allows updating protected branches so that #{access_type_name} can merge to them" do
visit project_protected_branches_path(project)
set_protected_branch_name('master')
-
- find(".js-allowed-to-merge").click
- within('[data-testid="allowed-to-merge-dropdown"]') do
- expect(first("li")).to have_content("Roles")
- find(:link, 'No one').click
- end
-
- find(".js-allowed-to-push").click
- within('[data-testid="allowed-to-push-dropdown"]') do
- expect(first("li")).to have_content("Roles")
- find(:link, 'No one').click
- end
-
+ set_allowed_to('merge', no_one)
+ set_allowed_to('push', no_one)
click_on_protect
expect(ProtectedBranch.count).to eq(1)
within(".protected-branches-list") do
- find(".js-allowed-to-merge").click
-
- within('.js-allowed-to-merge-container') do
- expect(first("li")).to have_content("Roles")
- find(:link, access_type_name).click
+ within_select(".js-allowed-to-merge") do
+ click_on(access_type_name)
end
end
diff --git a/spec/support/shared_examples/features/protected_tags_with_deploy_keys_examples.rb b/spec/support/shared_examples/features/protected_tags_with_deploy_keys_examples.rb
new file mode 100644
index 00000000000..cc0984b6226
--- /dev/null
+++ b/spec/support/shared_examples/features/protected_tags_with_deploy_keys_examples.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'Deploy keys with protected tags' do
+ 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 create' main dropdown, with only one deploy key" do
+ visit project_protected_tags_path(project)
+
+ find(".js-allowed-to-create").click
+ wait_for_requests
+
+ within('[data-testid="allowed-to-create-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 in the 'Allowed to create' update dropdown" do
+ create(:protected_tag, :no_one_can_create, project: project, name: 'v1.0.0')
+
+ visit project_protected_tags_path(project)
+
+ within(".js-protected-tag-edit-form") do
+ find(".js-allowed-to-create").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 create' dropdown" do
+ visit project_protected_tags_path(project)
+
+ find(".js-allowed-to-create").click
+ wait_for_requests
+
+ within('[data-testid="allowed-to-create-dropdown"]') do
+ 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/reportable_note_shared_examples.rb b/spec/support/shared_examples/features/reportable_note_shared_examples.rb
index bb3fab5b23e..133da230bed 100644
--- a/spec/support/shared_examples/features/reportable_note_shared_examples.rb
+++ b/spec/support/shared_examples/features/reportable_note_shared_examples.rb
@@ -20,7 +20,7 @@ RSpec.shared_examples 'reportable note' do |type|
dropdown = comment.find(more_actions_selector)
open_dropdown(dropdown)
- expect(dropdown).to have_button('Report abuse to administrator')
+ expect(dropdown).to have_button('Report abuse')
if type == 'issue' || type == 'merge_request'
expect(dropdown).to have_button('Delete comment')
@@ -33,7 +33,7 @@ RSpec.shared_examples 'reportable note' do |type|
dropdown = comment.find(more_actions_selector)
open_dropdown(dropdown)
- dropdown.click_button('Report abuse to administrator')
+ dropdown.click_button('Report abuse')
choose "They're posting spam."
click_button "Next"
@@ -48,6 +48,6 @@ RSpec.shared_examples 'reportable note' do |type|
restore_window_size
dropdown.find('.more-actions-toggle').click
- dropdown.find('.dropdown-menu li', match: :first)
+ dropdown.find('.more-actions li', match: :first)
end
end
diff --git a/spec/support/shared_examples/features/rss_shared_examples.rb b/spec/support/shared_examples/features/rss_shared_examples.rb
index ad865b084e1..f6566214e32 100644
--- a/spec/support/shared_examples/features/rss_shared_examples.rb
+++ b/spec/support/shared_examples/features/rss_shared_examples.rb
@@ -13,6 +13,12 @@ RSpec.shared_examples "it has an RSS button with current_user's feed token" do
end
end
+RSpec.shared_examples "it has an RSS link with current_user's feed token" do
+ it "shows the RSS link with current_user's feed token" do
+ expect(page).to have_link 'Subscribe to RSS feed', href: /feed_token=#{user.feed_token}/
+ end
+end
+
RSpec.shared_examples "an autodiscoverable RSS feed without a feed token" do
it "has an RSS autodiscovery link tag without a feed token" do
expect(page).to have_css("link[type*='atom+xml']:not([href*='feed_token'])", visible: false)
@@ -26,10 +32,18 @@ RSpec.shared_examples "it has an RSS button without a feed token" do
end
end
+RSpec.shared_examples "it has an RSS link without a feed token" do
+ it "shows the RSS link without a feed token" do
+ expect(page).to have_link 'Subscribe to RSS feed'
+ expect(page).not_to have_link 'Subscribe to RSS feed', href: /feed_token/
+ end
+end
+
RSpec.shared_examples "updates atom feed link" do |type|
it "for #{type}" do
sign_in(user)
visit path
+ click_button 'Actions', match: :first
link = find_link('Subscribe to RSS feed')
params = CGI.parse(URI.parse(link[:href]).query)
diff --git a/spec/support/shared_examples/features/runners_shared_examples.rb b/spec/support/shared_examples/features/runners_shared_examples.rb
index 63a0832117d..7edf306183e 100644
--- a/spec/support/shared_examples/features/runners_shared_examples.rb
+++ b/spec/support/shared_examples/features/runners_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples 'shows and resets runner registration token' do
- include Spec::Support::Helpers::Features::RunnersHelpers
+ include Features::RunnersHelpers
include Spec::Support::Helpers::ModalHelpers
before do
@@ -63,16 +63,15 @@ RSpec.shared_examples 'shows and resets runner registration token' do
end
RSpec.shared_examples 'shows no runners registered' do
- it 'shows total count with 0' do
+ it 'shows 0 count and the empty state' do
expect(find('[data-testid="runner-type-tabs"]')).to have_text "#{s_('Runners|All')} 0"
# No stats are shown
expect(page).not_to have_text s_('Runners|Online')
expect(page).not_to have_text s_('Runners|Offline')
expect(page).not_to have_text s_('Runners|Stale')
- end
- it 'shows "no runners" message' do
+ # "no runners" message
expect(page).to have_text s_('Runners|Get started with runners')
end
end
@@ -84,16 +83,14 @@ RSpec.shared_examples 'shows no runners found' do
end
RSpec.shared_examples 'shows runner in list' do
- it 'does not show empty state' do
- expect(page).not_to have_content s_('Runners|Get started with runners')
- end
-
- it 'shows runner row' do
+ it 'shows runner row and no empty state' do
within_runner_row(runner.id) do
expect(page).to have_text "##{runner.id}"
expect(page).to have_text runner.short_sha
expect(page).to have_text runner.description
end
+
+ expect(page).not_to have_content s_('Runners|Get started with runners')
end
end
@@ -229,3 +226,33 @@ RSpec.shared_examples 'submits edit runner form' do
end
end
end
+
+RSpec.shared_examples 'creates runner and shows register page' do
+ context 'when runner is saved' do
+ before do
+ fill_in s_('Runners|Runner description'), with: 'runner-foo'
+ fill_in s_('Runners|Tags'), with: 'tag1'
+ click_on _('Submit')
+ wait_for_requests
+ end
+
+ it 'navigates to registration page and opens install instructions drawer' do
+ expect(page.find('[data-testid="alert-success"]')).to have_content(s_('Runners|Runner created.'))
+ expect(current_url).to match(register_path_pattern)
+
+ click_on 'How do I install GitLab Runner?'
+ expect(page.find('[data-testid="runner-platforms-drawer"]')).to have_content('gitlab-runner install')
+ end
+
+ it 'warns from leaving page without finishing registration' do
+ click_on s_('Runners|Go to runners page')
+
+ alert = page.driver.browser.switch_to.alert
+
+ expect(alert).not_to be_nil
+ alert.dismiss
+
+ expect(current_url).to match(register_path_pattern)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/search/redacted_search_results_shared_examples.rb b/spec/support/shared_examples/features/search/redacted_search_results_shared_examples.rb
index 4d242d0e719..cbd0ffbab21 100644
--- a/spec/support/shared_examples/features/search/redacted_search_results_shared_examples.rb
+++ b/spec/support/shared_examples/features/search/redacted_search_results_shared_examples.rb
@@ -48,14 +48,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible issue' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'Issue', id: unreadable.id, ability: :read_issue }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'Issue', id: unreadable.id, ability: :read_issue }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -95,16 +99,18 @@ RSpec.shared_examples 'a redacted search results' do
end
let(:unredacted_results) do
- ar_relation(Note,
- readable_note_on_commit,
- readable_diff_note,
- readable_note_on_mr,
- readable_diff_note_on_mr,
- readable_note_on_project_snippet,
- unreadable_note_on_commit,
- unreadable_diff_note,
- unreadable_note_on_mr,
- unreadable_note_on_project_snippet)
+ ar_relation(
+ Note,
+ readable_note_on_commit,
+ readable_diff_note,
+ readable_note_on_mr,
+ readable_diff_note_on_mr,
+ readable_note_on_project_snippet,
+ unreadable_note_on_commit,
+ unreadable_diff_note,
+ unreadable_note_on_mr,
+ unreadable_note_on_project_snippet
+ )
end
let(:scope) { 'notes' }
@@ -112,23 +118,29 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible notes' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'Note', id: unreadable_note_on_commit.id, ability: :read_note },
- { class_name: 'DiffNote', id: unreadable_diff_note.id, ability: :read_note },
- { class_name: 'DiscussionNote', id: unreadable_note_on_mr.id, ability: :read_note },
- { class_name: 'Note', id: unreadable_note_on_project_snippet.id, ability: :read_note }
- ])))
-
- expect(result).to contain_exactly(readable_note_on_commit,
- readable_diff_note,
- readable_note_on_mr,
- readable_diff_note_on_mr,
- readable_note_on_project_snippet)
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'Note', id: unreadable_note_on_commit.id, ability: :read_note },
+ { class_name: 'DiffNote', id: unreadable_diff_note.id, ability: :read_note },
+ { class_name: 'DiscussionNote', id: unreadable_note_on_mr.id, ability: :read_note },
+ { class_name: 'Note', id: unreadable_note_on_project_snippet.id, ability: :read_note }
+ ]
+ )
+ )
+ )
+
+ expect(result).to contain_exactly(
+ readable_note_on_commit,
+ readable_diff_note,
+ readable_note_on_mr,
+ readable_diff_note_on_mr,
+ readable_note_on_project_snippet
+ )
end
end
@@ -141,14 +153,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible merge request' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'MergeRequest', id: unreadable.id, ability: :read_merge_request }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'MergeRequest', id: unreadable.id, ability: :read_merge_request }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -169,14 +185,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible blob' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'Gitlab::Search::FoundBlob', id: unreadable.id, ability: :read_blob }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'Gitlab::Search::FoundBlob', id: unreadable.id, ability: :read_blob }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -191,14 +211,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible blob' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'Gitlab::Search::FoundWikiPage', id: unreadable.id, ability: :read_wiki_page }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'Gitlab::Search::FoundWikiPage', id: unreadable.id, ability: :read_wiki_page }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -213,14 +237,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible snippet' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'ProjectSnippet', id: unreadable.id, ability: :read_snippet }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'ProjectSnippet', id: unreadable.id, ability: :read_snippet }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -239,14 +267,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible snippet' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'PersonalSnippet', id: unreadable.id, ability: :read_snippet }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'PersonalSnippet', id: unreadable.id, ability: :read_snippet }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
@@ -265,14 +297,18 @@ RSpec.shared_examples 'a redacted search results' do
it 'redacts the inaccessible commit' do
expect(search_service.send(:logger))
.to receive(:error)
- .with(hash_including(
- message: "redacted_search_results",
- current_user_id: user.id,
- query: search,
- filtered: array_including(
- [
- { class_name: 'Commit', id: unreadable.id, ability: :read_commit }
- ])))
+ .with(
+ hash_including(
+ message: "redacted_search_results",
+ current_user_id: user.id,
+ query: search,
+ filtered: array_including(
+ [
+ { class_name: 'Commit', id: unreadable.id, ability: :read_commit }
+ ]
+ )
+ )
+ )
expect(result).to contain_exactly(readable)
end
diff --git a/spec/support/shared_examples/features/secure_oauth_authorizations_shared_examples.rb b/spec/support/shared_examples/features/secure_oauth_authorizations_shared_examples.rb
index 028e075c87a..231406289b4 100644
--- a/spec/support/shared_examples/features/secure_oauth_authorizations_shared_examples.rb
+++ b/spec/support/shared_examples/features/secure_oauth_authorizations_shared_examples.rb
@@ -10,7 +10,7 @@ RSpec.shared_examples 'Secure OAuth Authorizations' do
end
context 'when user is unconfirmed' do
- let(:user) { create(:user, confirmed_at: nil) }
+ let(:user) { create(:user, :unconfirmed) }
it 'displays an error' do
expect(page).to have_text I18n.t('doorkeeper.errors.messages.unconfirmed_email')
diff --git a/spec/support/shared_examples/features/trial_email_validation_shared_example.rb b/spec/support/shared_examples/features/trial_email_validation_shared_example.rb
index 8304a91af86..81c9ac1164b 100644
--- a/spec/support/shared_examples/features/trial_email_validation_shared_example.rb
+++ b/spec/support/shared_examples/features/trial_email_validation_shared_example.rb
@@ -1,59 +1,38 @@
# frozen_string_literal: true
RSpec.shared_examples 'user email validation' do
- let(:email_hint_message) { 'We recommend a work email address.' }
- let(:email_error_message) { 'Please provide a valid email address.' }
+ let(:email_hint_message) { _('We recommend a work email address.') }
+ let(:email_error_message) { _('Please provide a valid email address.') }
let(:email_warning_message) do
- 'This email address does not look right, are you sure you typed it correctly?'
+ _('This email address does not look right, are you sure you typed it correctly?')
end
- context 'with trial_email_validation flag enabled' do
- it 'shows an error message until a correct email is entered' do
- visit path
- expect(page).to have_content(email_hint_message)
- expect(page).not_to have_content(email_error_message)
- expect(page).not_to have_content(email_warning_message)
+ it 'shows an error message until a correct email is entered' do
+ visit path
+ expect(page).to have_content(email_hint_message)
+ expect(page).not_to have_content(email_error_message)
+ expect(page).not_to have_content(email_warning_message)
- fill_in 'new_user_email', with: 'foo@'
- fill_in 'new_user_first_name', with: ''
+ fill_in 'new_user_email', with: 'foo@'
+ fill_in 'new_user_first_name', with: ''
- expect(page).not_to have_content(email_hint_message)
- expect(page).to have_content(email_error_message)
- expect(page).not_to have_content(email_warning_message)
+ expect(page).not_to have_content(email_hint_message)
+ expect(page).to have_content(email_error_message)
+ expect(page).not_to have_content(email_warning_message)
- fill_in 'new_user_email', with: 'foo@bar'
- fill_in 'new_user_first_name', with: ''
+ fill_in 'new_user_email', with: 'foo@bar'
+ fill_in 'new_user_first_name', with: ''
- expect(page).not_to have_content(email_hint_message)
- expect(page).not_to have_content(email_error_message)
- expect(page).to have_content(email_warning_message)
+ expect(page).not_to have_content(email_hint_message)
+ expect(page).not_to have_content(email_error_message)
+ expect(page).to have_content(email_warning_message)
- fill_in 'new_user_email', with: 'foo@gitlab.com'
- fill_in 'new_user_first_name', with: ''
+ fill_in 'new_user_email', with: 'foo@gitlab.com'
+ fill_in 'new_user_first_name', with: ''
- expect(page).not_to have_content(email_hint_message)
- expect(page).not_to have_content(email_error_message)
- expect(page).not_to have_content(email_warning_message)
- end
- end
-
- context 'when trial_email_validation flag disabled' do
- before do
- stub_feature_flags trial_email_validation: false
- end
-
- it 'does not show an error message' do
- visit path
- expect(page).to have_content(email_hint_message)
- expect(page).not_to have_content(email_error_message)
- expect(page).not_to have_content(email_warning_message)
-
- fill_in 'new_user_email', with: 'foo@'
-
- expect(page).to have_content(email_hint_message)
- expect(page).not_to have_content(email_error_message)
- expect(page).not_to have_content(email_warning_message)
- end
+ expect(page).not_to have_content(email_hint_message)
+ expect(page).not_to have_content(email_error_message)
+ expect(page).not_to have_content(email_warning_message)
end
end
diff --git a/spec/support/shared_examples/features/variable_list_pagination_shared_examples.rb b/spec/support/shared_examples/features/variable_list_pagination_shared_examples.rb
new file mode 100644
index 00000000000..0b0c9edcb42
--- /dev/null
+++ b/spec/support/shared_examples/features/variable_list_pagination_shared_examples.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'variable list pagination' do |variable_type|
+ first_page_count = 20
+
+ before do
+ first_page_count.times do |i|
+ case variable_type
+ when :ci_variable
+ create(variable_type, key: "test_key_#{i}", value: 'test_value', masked: true, project: project)
+ when :ci_group_variable
+ create(variable_type, key: "test_key_#{i}", value: 'test_value', masked: true, group: group)
+ else
+ create(variable_type, key: "test_key_#{i}", value: 'test_value', masked: true)
+ end
+ end
+
+ visit page_path
+ wait_for_requests
+ end
+
+ it 'can navigate between pages' do
+ page.within('[data-testid="ci-variable-table"]') do
+ expect(page.all('.js-ci-variable-row').length).to be(first_page_count)
+ end
+
+ click_button 'Next'
+ wait_for_requests
+
+ page.within('[data-testid="ci-variable-table"]') do
+ expect(page.all('.js-ci-variable-row').length).to be(1)
+ end
+
+ click_button 'Previous'
+ wait_for_requests
+
+ page.within('[data-testid="ci-variable-table"]') do
+ expect(page.all('.js-ci-variable-row').length).to be(first_page_count)
+ end
+ end
+
+ it 'sorts variables alphabetically in ASC and DESC order' do
+ page.within('[data-testid="ci-variable-table"]') do
+ expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Key"]').text).to eq(variable.key)
+ expect(find('.js-ci-variable-row:nth-child(20) td[data-label="Key"]').text).to eq('test_key_8')
+ end
+
+ click_button 'Next'
+ wait_for_requests
+
+ page.within('[data-testid="ci-variable-table"]') do
+ expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Key"]').text).to eq('test_key_9')
+ end
+
+ page.within('[data-testid="ci-variable-table"]') do
+ find('.b-table-sort-icon-left').click
+ end
+
+ wait_for_requests
+
+ page.within('[data-testid="ci-variable-table"]') do
+ expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Key"]').text).to eq('test_key_9')
+ expect(find('.js-ci-variable-row:nth-child(20) td[data-label="Key"]').text).to eq('test_key_0')
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/variable_list_shared_examples.rb b/spec/support/shared_examples/features/variable_list_shared_examples.rb
index f0b72cfaee3..1211c9d19e6 100644
--- a/spec/support/shared_examples/features/variable_list_shared_examples.rb
+++ b/spec/support/shared_examples/features/variable_list_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples 'variable list' do |is_admin|
+RSpec.shared_examples 'variable list' do
it 'shows a list of variables' do
page.within('[data-testid="ci-variable-table"]') do
expect(find('.js-ci-variable-row:nth-child(1) td[data-label="Key"]').text).to eq(variable.key)
@@ -256,14 +256,6 @@ RSpec.shared_examples 'variable list' do |is_admin|
expect(find('[data-testid="ci-variable-protected-checkbox"]')).to be_checked
end
end
-
- it 'shows a message regarding the changed default' do
- if is_admin
- expect(page).to have_content 'Environment variables on this GitLab instance are configured to be protected by default'
- else
- expect(page).to have_content 'Environment variables are configured by your administrator to be protected by default'
- end
- end
end
context 'application setting is false' do
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 7a3b94ad81d..6451c531aec 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
@@ -62,7 +62,7 @@ RSpec.shared_examples 'wiki file attachments' do
attach_with_dropzone(true)
wait_for_requests
- find('.js-md-preview-button').click
+ click_button("Preview")
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']
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
index 3e285bb8ad7..ca68df9a89b 100644
--- 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
@@ -78,7 +78,7 @@ RSpec.shared_examples 'User previews wiki changes' do
it_behaves_like 'relative links' do
before do
- click_on 'Preview'
+ click_button("Preview")
end
let(:element) { preview }
@@ -88,7 +88,7 @@ RSpec.shared_examples 'User previews wiki changes' do
# using two `\n` ensures we're sublist to it's own line due
# to list auto-continue
fill_in :wiki_content, with: "1. one\n\n - sublist\n"
- click_on "Preview"
+ click_button("Preview")
# the above generates two separate lists (not embedded) in CommonMark
expect(preview).to have_content("sublist")
@@ -102,7 +102,7 @@ RSpec.shared_examples 'User previews wiki changes' do
[[also_do_not_linkify]]
```
HEREDOC
- click_on "Preview"
+ click_button("Preview")
expect(preview).to have_content("do_not_linkify")
expect(preview).to have_content('[[do_not_linkify]]')
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
index 0334187e4b1..c1e4185e058 100644
--- 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
@@ -150,6 +150,7 @@ RSpec.shared_examples 'User updates wiki page' do
end
it_behaves_like 'edits content using the content editor'
+ it_behaves_like 'inserts diagrams.net diagram using the content editor'
it_behaves_like 'autocompletes items'
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
index a7c32932ba7..767caffd417 100644
--- 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
@@ -9,9 +9,11 @@ RSpec.shared_examples 'User views a wiki page' do
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})")
+ create(
+ :wiki_page,
+ wiki: wiki,
+ title: 'home', content: "Look at this [image](#{path})\n\n ![alt text](#{path})"
+ )
end
before do
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
index 639eb3f2b99..21c7e2b6c75 100644
--- 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
@@ -84,6 +84,44 @@ RSpec.shared_examples 'User views wiki sidebar' do
expect(page).not_to have_link('View All Pages')
end
+ it 'shows all collapse buttons in the sidebar' do
+ visit wiki_path(wiki)
+
+ within('.right-sidebar') do
+ expect(page.all("[data-testid='chevron-down-icon']").size).to eq(3)
+ end
+ end
+
+ it 'collapses/expands children when click collapse/expand button in the sidebar', :js do
+ visit wiki_path(wiki)
+
+ within('.right-sidebar') do
+ first("[data-testid='chevron-down-icon']").click
+ (11..15).each { |i| expect(page).not_to have_content("my page #{i}") }
+ expect(page.all("[data-testid='chevron-down-icon']").size).to eq(1)
+ expect(page.all("[data-testid='chevron-right-icon']").size).to eq(1)
+
+ first("[data-testid='chevron-right-icon']").click
+ (11..15).each { |i| expect(page).to have_content("my page #{i}") }
+ expect(page.all("[data-testid='chevron-down-icon']").size).to eq(3)
+ expect(page.all("[data-testid='chevron-right-icon']").size).to eq(0)
+ end
+ end
+
+ it 'shows create child page button when hover to the page title in the sidebar', :js do
+ visit wiki_path(wiki)
+
+ within('.right-sidebar') do
+ first_wiki_list = first("[data-testid='wiki-list']")
+ wiki_link = first("[data-testid='wiki-list'] a:last-of-type")['href']
+
+ first_wiki_list.hover
+ wiki_new_page_link = first("[data-testid='wiki-list'] a")['href']
+
+ expect(wiki_new_page_link).to eq "#{wiki_link}/%7Bnew_page_title%7D"
+ end
+ end
+
context 'when there are more than 15 existing pages' do
before do
create(:wiki_page, wiki: wiki, title: 'my page 16')
diff --git a/spec/support/shared_examples/features/work_items_shared_examples.rb b/spec/support/shared_examples/features/work_items_shared_examples.rb
index 4f3d957ad71..526a56e7dab 100644
--- a/spec/support/shared_examples/features/work_items_shared_examples.rb
+++ b/spec/support/shared_examples/features/work_items_shared_examples.rb
@@ -1,5 +1,20 @@
# frozen_string_literal: true
+RSpec.shared_examples 'work items title' do
+ let(:title_selector) { '[data-testid="work-item-title"]' }
+
+ it 'successfully shows and changes the title of the work item' do
+ expect(work_item.reload.title).to eq work_item.title
+
+ find(title_selector).set("Work item title")
+ find(title_selector).native.send_keys(:return)
+
+ wait_for_requests
+
+ expect(work_item.reload.title).to eq 'Work item title'
+ end
+end
+
RSpec.shared_examples 'work items status' do
let(:state_selector) { '[data-testid="work-item-state-select"]' }
@@ -15,18 +30,110 @@ RSpec.shared_examples 'work items status' do
end
end
-RSpec.shared_examples 'work items comments' do
+RSpec.shared_examples 'work items comments' do |type|
let(:form_selector) { '[data-testid="work-item-add-comment"]' }
+ let(:textarea_selector) { '[data-testid="work-item-add-comment"] #work-item-add-or-edit-comment' }
+ let(:is_mac) { page.evaluate_script('navigator.platform').include?('Mac') }
+ let(:modifier_key) { is_mac ? :command : :control }
+ let(:comment) { 'Test comment' }
+
+ def set_comment
+ find(form_selector).fill_in(with: comment)
+ end
it 'successfully creates and shows comments' do
- click_button 'Add a comment'
+ set_comment
- find(form_selector).fill_in(with: "Test comment")
click_button "Comment"
wait_for_requests
- expect(page).to have_content "Test comment"
+ page.within(".main-notes-list") do
+ expect(page).to have_content comment
+ end
+ end
+
+ context 'for work item note actions signed in user with developer role' do
+ it 'shows work item note actions' do
+ set_comment
+
+ click_button "Comment"
+
+ wait_for_requests
+
+ page.within(".main-notes-list") do
+ expect(page).to have_selector('[data-testid="work-item-note-actions"]')
+
+ find('[data-testid="work-item-note-actions"]', match: :first).click
+
+ expect(page).to have_selector('[data-testid="copy-link-action"]')
+ expect(page).not_to have_selector('[data-testid="assign-note-action"]')
+ end
+ end
+ end
+
+ it 'successfully posts comments using shortcut and checks if textarea is blank when reinitiated' do
+ set_comment
+
+ send_keys([modifier_key, :enter])
+
+ wait_for_requests
+
+ page.within(".main-notes-list") do
+ expect(page).to have_content comment
+ end
+
+ expect(find(textarea_selector)).to have_content ""
+ end
+
+ context 'when using quick actions' do
+ it 'autocompletes quick actions common to all work item types', :aggregate_failures do
+ click_reply_and_enter_slash
+
+ page.within('#at-view-commands') do
+ expect(page).to have_text("/title")
+ expect(page).to have_text("/shrug")
+ expect(page).to have_text("/tableflip")
+ expect(page).to have_text("/close")
+ expect(page).to have_text("/cc")
+ end
+ end
+
+ context 'when a widget is enabled' do
+ before do
+ WorkItems::Type.default_by_type(type).widget_definitions
+ .find_by_widget_type(:assignees).update!(disabled: false)
+ end
+
+ it 'autocompletes quick action for the enabled widget' do
+ click_reply_and_enter_slash
+
+ page.within('#at-view-commands') do
+ expect(page).to have_text("/assign")
+ end
+ end
+ end
+
+ context 'when a widget is disabled' do
+ before do
+ WorkItems::Type.default_by_type(type).widget_definitions
+ .find_by_widget_type(:assignees).update!(disabled: true)
+ end
+
+ it 'does not autocomplete quick action for the disabled widget' do
+ click_reply_and_enter_slash
+
+ page.within('#at-view-commands') do
+ expect(page).not_to have_text("/assign")
+ end
+ end
+ end
+
+ def click_reply_and_enter_slash
+ find(form_selector).fill_in(with: "/")
+
+ wait_for_all_requests
+ end
end
end
@@ -39,7 +146,6 @@ RSpec.shared_examples 'work items assignees' do
# submit and simulate blur to save
send_keys(:enter)
find("body").click
-
wait_for_requests
expect(work_item.assignees).to include(user)
@@ -47,6 +153,8 @@ RSpec.shared_examples 'work items assignees' do
end
RSpec.shared_examples 'work items labels' do
+ let(:label_title_selector) { '[data-testid="labels-title"]' }
+
it 'successfully assigns a label' do
label = create(:label, project: work_item.project, title: "testing-label")
@@ -55,8 +163,7 @@ RSpec.shared_examples 'work items labels' do
# submit and simulate blur to save
send_keys(:enter)
- find("body").click
-
+ find(label_title_selector).click
wait_for_requests
expect(work_item.labels).to include(label)
@@ -83,7 +190,7 @@ RSpec.shared_examples 'work items description' do
wait_for_requests
- page.within('.atwho-container') do
+ page.within('#at-view-commands') do
expect(page).to have_text("title")
expect(page).to have_text("shrug")
expect(page).to have_text("tableflip")
@@ -125,7 +232,7 @@ RSpec.shared_examples 'work items description' do
end
RSpec.shared_examples 'work items invite members' do
- include Spec::Support::Helpers::Features::InviteMembersModalHelper
+ include Features::InviteMembersModalHelpers
it 'successfully assigns the current user by searching' do
# The button is only when the mouse is over the input
@@ -139,3 +246,143 @@ RSpec.shared_examples 'work items invite members' do
end
end
end
+
+RSpec.shared_examples 'work items milestone' do
+ def set_milestone(milestone_dropdown, milestone_text)
+ milestone_dropdown.click
+
+ find('[data-testid="work-item-milestone-dropdown"] .gl-form-input', visible: true).send_keys "\"#{milestone_text}\""
+ wait_for_requests
+
+ click_button(milestone_text)
+ wait_for_requests
+ end
+
+ let(:milestone_dropdown_selector) { '[data-testid="work-item-milestone-dropdown"]' }
+
+ it 'searches and sets or removes milestone for the work item' do
+ set_milestone(find(milestone_dropdown_selector), milestone.title)
+
+ expect(page.find(milestone_dropdown_selector)).to have_text(milestone.title)
+
+ set_milestone(find(milestone_dropdown_selector), 'No milestone')
+
+ expect(page.find(milestone_dropdown_selector)).to have_text('Add to milestone')
+ end
+end
+
+RSpec.shared_examples 'work items comment actions for guest users' do
+ context 'for guest user' do
+ it 'hides other actions other than copy link' do
+ page.within(".main-notes-list") do
+ expect(page).to have_selector('[data-testid="work-item-note-actions"]')
+
+ find('[data-testid="work-item-note-actions"]', match: :first).click
+
+ expect(page).to have_selector('[data-testid="copy-link-action"]')
+ expect(page).not_to have_selector('[data-testid="assign-note-action"]')
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'work items notifications' do
+ let(:actions_dropdown_selector) { '[data-testid="work-item-actions-dropdown"]' }
+ let(:notifications_toggle_selector) { '[data-testid="notifications-toggle-action"] > button' }
+
+ it 'displays toast when notification is toggled' do
+ find(actions_dropdown_selector).click
+
+ page.within('[data-testid="notifications-toggle-form"]') do
+ expect(page).not_to have_css(".is-checked")
+
+ find(notifications_toggle_selector).click
+ wait_for_requests
+
+ expect(page).to have_css(".is-checked")
+ end
+
+ page.within('.gl-toast') do
+ expect(find('.toast-body')).to have_content(_('Notifications turned on.'))
+ end
+ end
+end
+
+RSpec.shared_examples 'work items todos' do
+ let(:todos_action_selector) { '[data-testid="work-item-todos-action"]' }
+ let(:todos_icon_selector) { '[data-testid="work-item-todos-icon"]' }
+ let(:header_section_selector) { '[data-testid="work-item-body"]' }
+
+ def toggle_todo_action
+ find(todos_action_selector).click
+ wait_for_requests
+ end
+
+ it 'adds item to the list' do
+ page.within(header_section_selector) do
+ expect(find(todos_action_selector)['aria-label']).to eq('Add a to do')
+
+ toggle_todo_action
+
+ expect(find(todos_action_selector)['aria-label']).to eq('Mark as done')
+ end
+
+ page.within ".header-content span[aria-label='#{_('Todos count')}']" do
+ expect(page).to have_content '1'
+ end
+ end
+
+ it 'marks a todo as done' do
+ page.within(header_section_selector) do
+ toggle_todo_action
+ toggle_todo_action
+ end
+
+ expect(find(todos_action_selector)['aria-label']).to eq('Add a to do')
+ expect(page).to have_selector(".header-content span[aria-label='#{_('Todos count')}']", visible: :hidden)
+ end
+end
+
+RSpec.shared_examples 'work items award emoji' do
+ let(:award_section_selector) { '[data-testid="work-item-award-list"]' }
+ let(:award_action_selector) { '[data-testid="award-button"]' }
+ let(:selected_award_action_selector) { '[data-testid="award-button"].selected' }
+ let(:emoji_picker_action_selector) { '[data-testid="emoji-picker"]' }
+ let(:basketball_emoji_selector) { 'gl-emoji[data-name="basketball"]' }
+
+ def select_emoji
+ first(award_action_selector).click
+
+ wait_for_requests
+ end
+
+ it 'adds award to the work item' do
+ within(award_section_selector) do
+ select_emoji
+
+ expect(page).to have_selector(selected_award_action_selector)
+ expect(first(award_action_selector)).to have_content '1'
+ end
+ end
+
+ it 'removes award from work item' do
+ within(award_section_selector) do
+ select_emoji
+
+ expect(first(award_action_selector)).to have_content '1'
+
+ select_emoji
+
+ expect(first(award_action_selector)).to have_content '0'
+ end
+ end
+
+ it 'add custom award to the work item' do
+ within(award_section_selector) do
+ find(emoji_picker_action_selector).click
+ find(basketball_emoji_selector).click
+
+ expect(page).to have_selector(basketball_emoji_selector)
+ end
+ end
+end