summaryrefslogtreecommitdiffstats
path: root/test/system
diff options
context:
space:
mode:
Diffstat (limited to 'test/system')
-rw-r--r--test/system/issues_test.rb11
-rw-r--r--test/system/messages_test.rb4
-rw-r--r--test/system/oauth_provider_test.rb137
-rw-r--r--test/system/reactions_test.rb173
-rw-r--r--test/system/sticky_issue_header_test.rb38
-rw-r--r--test/system/sudo_mode_test.rb3
-rw-r--r--test/system/timelog_test.rb3
7 files changed, 366 insertions, 3 deletions
diff --git a/test/system/issues_test.rb b/test/system/issues_test.rb
index 80ef25e0c..c161538e7 100644
--- a/test/system/issues_test.rb
+++ b/test/system/issues_test.rb
@@ -34,6 +34,8 @@ class IssuesSystemTest < ApplicationSystemTestCase
find('input[name=commit]').click
end
+ assert_text /Issue #\d+ created./
+
# find created issue
issue = Issue.find_by_subject("new test issue")
assert_kind_of Issue, issue
@@ -86,6 +88,7 @@ class IssuesSystemTest < ApplicationSystemTestCase
fill_in field2.name, :with => 'CF2 value'
assert_difference 'Issue.count' do
page.first(:button, 'Create').click
+ assert_text /Issue #\d+ created./
end
issue = Issue.order('id desc').first
@@ -125,6 +128,7 @@ class IssuesSystemTest < ApplicationSystemTestCase
end
assert_difference 'Issue.count' do
find('input[name=commit]').click
+ assert_text /Issue #\d+ created./
end
issue = Issue.order('id desc').first
@@ -141,6 +145,7 @@ class IssuesSystemTest < ApplicationSystemTestCase
attach_file 'attachments[dummy][file]', Rails.root.join('test/fixtures/files/testfile.txt')
fill_in 'attachments[1][description]', :with => 'Some description'
click_on 'Create'
+ assert_text /Issue #\d+ created./
end
assert_equal 1, issue.attachments.count
assert_equal 'Some description', issue.attachments.first.description
@@ -163,6 +168,7 @@ class IssuesSystemTest < ApplicationSystemTestCase
attach_file 'attachments[dummy][file]', Rails.root.join('test/fixtures/files/testfile.txt')
fill_in 'attachments[1][description]', :with => 'Some description'
click_on 'Create'
+ assert_text /Issue #\d+ created./
end
assert_equal 1, issue.attachments.count
assert_equal 'Some description', issue.attachments.first.description
@@ -181,6 +187,7 @@ class IssuesSystemTest < ApplicationSystemTestCase
click_on 'Create'
end
click_on 'Create'
+ assert_text /Issue #\d+ created./
end
end
@@ -200,6 +207,7 @@ class IssuesSystemTest < ApplicationSystemTestCase
end
assert_difference 'Issue.count' do
click_button('Create')
+ assert_text /Issue #\d+ created./
end
issue = Issue.order('id desc').first
@@ -230,6 +238,7 @@ class IssuesSystemTest < ApplicationSystemTestCase
fill_in 'Form update CF', :with => 'CF value'
assert_no_difference 'Issue.count' do
page.first(:button, 'Submit').click
+ assert_text 'Successful update.'
end
assert page.has_css?('#flash_notice')
issue = Issue.find(1)
@@ -245,6 +254,7 @@ class IssuesSystemTest < ApplicationSystemTestCase
page.find("#issue_status_id").select("Closed")
assert_no_difference 'Issue.count' do
page.first(:button, 'Submit').click
+ assert_text 'Successful update.'
end
assert page.has_css?('#flash_notice')
assert_equal 5, issue.reload.status.id
@@ -267,6 +277,7 @@ class IssuesSystemTest < ApplicationSystemTestCase
click_on 'Submit'
+ assert_text 'Successful update.'
assert_equal 3, Issue.find(2).attachments.count
end
diff --git a/test/system/messages_test.rb b/test/system/messages_test.rb
index 66a29a3a7..ac074ac1a 100644
--- a/test/system/messages_test.rb
+++ b/test/system/messages_test.rb
@@ -22,7 +22,7 @@ require_relative '../application_system_test_case'
class MessagesTest < ApplicationSystemTestCase
def test_reply_to_topic_message
with_text_formatting 'common_mark' do
- within '#content > .contextual' do
+ within '#content > [data-controller="quote-reply"]' do
click_link 'Quote'
end
@@ -64,7 +64,7 @@ class MessagesTest < ApplicationSystemTestCase
window.getSelection().addRange(range);
JS
- within '#content > .contextual' do
+ within '#content > [data-controller="quote-reply"]' do
click_link 'Quote'
end
diff --git a/test/system/oauth_provider_test.rb b/test/system/oauth_provider_test.rb
new file mode 100644
index 000000000..364ed4c94
--- /dev/null
+++ b/test/system/oauth_provider_test.rb
@@ -0,0 +1,137 @@
+# frozen_string_literal: true
+
+require_relative '../application_system_test_case'
+require 'oauth2'
+require 'rack'
+require 'puma'
+
+class OauthProviderSystemTest < ApplicationSystemTestCase
+ fixtures :projects, :users, :email_addresses, :roles, :members, :member_roles,
+ :trackers, :projects_trackers, :enabled_modules, :issue_statuses, :issues,
+ :enumerations, :custom_fields, :custom_values, :custom_fields_trackers,
+ :watchers, :journals, :journal_details, :versions,
+ :workflows
+
+ test 'application creation and authorization' do
+ #
+ # admin creates the application, granting permissions and generating a uuid
+ # and secret.
+ #
+ log_user 'admin', 'admin'
+ with_settings rest_api_enabled: 1 do
+ visit '/admin'
+ within 'div#admin-menu ul' do
+ click_link 'Applications'
+ end
+ click_link 'New Application'
+ fill_in 'Name', with: 'Oauth Test'
+
+ # as per https://tools.ietf.org/html/rfc8252#section-7.3, the port can be
+ # anything when the redirect URI's host is 127.0.0.1.
+ fill_in 'Redirect URI', with: 'http://127.0.0.1'
+
+ check 'View Issues'
+ click_button 'Create'
+
+ assert_text "Application created."
+ end
+
+ assert app = Doorkeeper::Application.find_by_name('Oauth Test')
+
+ find 'h2', visible: true, text: /Oauth Test/
+ find 'p code', visible: true, text: app.uid
+ find 'p strong', visible: true, text: /will not be shown again/
+ find 'p code', visible: true, text: /View Issues/
+
+ # scrape the clear text secret from the page
+ app_secret = all(:css, 'p code')[1].text
+
+ click_link 'Sign out'
+
+ #
+ # regular user authorizes the application
+ #
+ client = OAuth2::Client.new(app.uid, app_secret, site: "http://127.0.0.1:#{test_port}/")
+
+ # set up a dummy http listener to handle the redirect
+ port = rand 10000..20000
+ redirect_uri = "http://127.0.0.1:#{port}"
+ # the request handler below will set this to the auth token
+ token = nil
+
+ # launches webrick, listening for the redirect with the auth code.
+ launch_client_app(port: port) do |req, res|
+ # get access code from code url param
+ if code = req.params['code'].presence
+ # exchange it for token
+ token = client.auth_code.get_token(code, redirect_uri: redirect_uri)
+ res.body = ["<html><body><p>Authorization succeeded, you may close this window now.</p></body></html>"]
+ end
+ end
+
+ log_user 'jsmith', 'jsmith'
+ with_settings rest_api_enabled: 1 do
+ visit '/my/account'
+ click_link 'Authorized applications'
+ find 'p.nodata', visible: true
+
+ # an oauth client would send the user to this url to request permission
+ url = client.auth_code.authorize_url redirect_uri: redirect_uri, scope: 'view_issues view_project'
+ uri = URI.parse url
+ visit uri.path + '?' + uri.query
+
+ find 'h2', visible: true, text: 'Authorization required'
+ find 'p', visible: true, text: /Authorize Oauth Test/
+ find '.oauth-permissions', visible: true, text: /View Issues/
+ find '.oauth-permissions', visible: true, text: /View project/
+
+ click_button 'Authorize'
+
+ assert grant = app.access_grants.last
+ assert_equal 'view_issues view_project', grant.scopes.to_s
+
+ # check for output defined above in the request handler
+ find 'p', visible: true, text: /Authorization succeeded/
+ assert token.present?
+
+ visit '/my/account'
+ click_link 'Authorized applications'
+ find 'td', visible: true, text: /Oauth Test/
+ click_link 'Sign out'
+
+ # Now, use the token for some API requests
+ assert_raise(RestClient::Unauthorized) do
+ RestClient.get "http://localhost:#{test_port}/projects/onlinestore/issues.json"
+ end
+
+ headers = { 'Authorization' => "Bearer #{token.token}" }
+ r = RestClient.get "http://localhost:#{test_port}/projects/onlinestore/issues.json", headers
+ issues = JSON.parse(r.body)['issues']
+ assert issues.any?
+
+ # time entries access is not part of the granted scopes
+ assert_raise(RestClient::Forbidden) do
+ RestClient.get "http://localhost:#{test_port}/projects/onlinestore/time_entries.json", headers
+ end
+ end
+ end
+
+ private
+
+ def launch_client_app(port: 12345, path: '/', &block)
+ app = ->(env) do
+ req = Rack::Request.new(env)
+ res = Rack::Response.new
+ yield(req, res)
+ res.finish
+ end
+
+ server = Puma::Server.new app
+ server.add_tcp_listener '127.0.0.1', port
+ Thread.new { server.run }
+ end
+
+ def test_port
+ Capybara.current_session.server.port
+ end
+end
diff --git a/test/system/reactions_test.rb b/test/system/reactions_test.rb
new file mode 100644
index 000000000..96dd4cf81
--- /dev/null
+++ b/test/system/reactions_test.rb
@@ -0,0 +1,173 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006- Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require_relative '../application_system_test_case'
+
+class ReactionsSystemTest < ApplicationSystemTestCase
+ def test_react_to_issue
+ log_user('jsmith', 'jsmith')
+
+ issue = issues(:issues_002)
+
+ with_settings(reactions_enabled: '1') do
+ visit '/issues/2'
+ reaction_button = find("div.issue.details [data-reaction-button-id=\"reaction_issue_#{issue.id}\"]")
+ assert_reaction_add_and_remove(reaction_button, issue)
+ end
+ end
+
+ def test_react_to_journal
+ log_user('jsmith', 'jsmith')
+
+ journal = journals(:journals_002)
+
+ with_settings(reactions_enabled: '1') do
+ visit '/issues/1'
+ reaction_button = find("[data-reaction-button-id=\"reaction_journal_#{journal.id}\"]")
+ assert_reaction_add_and_remove(reaction_button, journal.reload)
+ end
+ end
+
+ def test_react_to_forum_reply
+ log_user('jsmith', 'jsmith')
+
+ reply_message = messages(:messages_002) # reply to message_001
+
+ with_settings(reactions_enabled: '1') do
+ visit 'boards/1/topics/1'
+ reaction_button = find("[data-reaction-button-id=\"reaction_message_#{reply_message.id}\"]")
+ assert_reaction_add_and_remove(reaction_button, reply_message)
+ end
+ end
+
+ def test_react_to_forum_message
+ log_user('jsmith', 'jsmith')
+
+ message = messages(:messages_001)
+
+ with_settings(reactions_enabled: '1') do
+ visit 'boards/1/topics/1'
+ reaction_button = find("[data-reaction-button-id=\"reaction_message_#{message.id}\"]")
+ assert_reaction_add_and_remove(reaction_button, message)
+ end
+ end
+
+ def test_react_to_news
+ log_user('jsmith', 'jsmith')
+
+ with_settings(reactions_enabled: '1') do
+ visit '/news/2'
+ reaction_button = find("[data-reaction-button-id=\"reaction_news_2\"]")
+ assert_reaction_add_and_remove(reaction_button, news(:news_002))
+ end
+ end
+
+ def test_react_to_comment
+ log_user('jsmith', 'jsmith')
+
+ comment = comments(:comments_002)
+
+ with_settings(reactions_enabled: '1') do
+ visit '/news/1'
+ reaction_button = find("[data-reaction-button-id=\"reaction_comment_#{comment.id}\"]")
+ assert_reaction_add_and_remove(reaction_button, comment)
+ end
+ end
+
+ def test_reactions_disabled
+ log_user('jsmith', 'jsmith')
+
+ with_settings(reactions_enabled: '0') do
+ visit '/issues/1'
+ assert_no_selector('[data-reaction-button-id="reaction_issue_1"]')
+ end
+ end
+
+ def test_reaction_button_is_visible_but_not_clickable_for_not_logged_in_user
+ with_settings(reactions_enabled: '1') do
+ visit '/issues/1'
+
+ # visible
+ reaction_button = find('div.issue.details [data-reaction-button-id="reaction_issue_1"]')
+ within(reaction_button) { assert_selector('span.reaction-button') }
+ assert_equal "3", reaction_button.text
+
+ # not clickable
+ within(reaction_button) { assert_no_selector('a.reaction-button') }
+ end
+ end
+
+ def test_reaction_button_is_visible_on_property_changes_tab
+ # Create a journal with no notes
+ journal_without_notes = Journal.generate!(journalized: issues(:issues_001), notes: '', details: [JournalDetail.new])
+
+ log_user('jsmith', 'jsmith')
+
+ visit '/issues/1?tab=properties'
+
+ # Scroll to the history content
+ click_link '#1'
+
+ assert_selector '#tab-properties.selected'
+
+ within('#change-1') do
+ assert_selector 'a.reaction-button'
+
+ assert_no_selector 'a.icon-quote'
+ assert_no_selector 'span.drdn'
+ end
+ within("#change-#{journal_without_notes.id}") do
+ assert_selector 'a.reaction-button'
+
+ assert_no_selector '.drdn'
+ end
+
+ click_link 'History'
+
+ within('#change-1') do
+ assert_selector 'a.reaction-button'
+
+ assert_selector 'a.icon-quote'
+ assert_selector 'span.drdn'
+ end
+ within("#change-#{journal_without_notes.id}") do
+ assert_selector 'a.reaction-button'
+ assert_selector 'span.drdn'
+
+ assert_no_selector 'a.icon-quote'
+ end
+ end
+
+ private
+
+ def assert_reaction_add_and_remove(reaction_button, expected_subject)
+ # Add a reaction
+ within(reaction_button) { find('a.reaction-button').click }
+ find('body').hover # Hide tooltip
+ within(reaction_button) { assert_selector('a.reaction-button.reacted[title="John Smith"]') }
+ assert_equal "1", reaction_button.text
+ assert_equal 1, expected_subject.reactions.count
+
+ # Remove the reaction
+ within(reaction_button) { find('a.reacted').click }
+ within(reaction_button) { assert_selector('a.reaction-button:not(.reacted)') }
+ assert_equal "", reaction_button.text
+ assert_equal 0, expected_subject.reactions.count
+ end
+end
diff --git a/test/system/sticky_issue_header_test.rb b/test/system/sticky_issue_header_test.rb
new file mode 100644
index 000000000..5c67b36f3
--- /dev/null
+++ b/test/system/sticky_issue_header_test.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006- Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+require_relative '../application_system_test_case'
+class StickyIssueHeaderSystemTest < ApplicationSystemTestCase
+ test "sticky issue header is hidden by default" do
+ issue = Issue.find(1)
+ visit issue_path(issue)
+
+ assert_no_selector "#sticky-issue-header", text: issue.subject
+ end
+
+ test "sticky issue header appears on scroll" do
+ issue = Issue.find(2)
+ visit issue_path(issue)
+
+ page.execute_script("window.scrollTo(0, 1000)")
+ assert_selector "#sticky-issue-header.is-visible", text: issue.subject
+
+ page.execute_script("window.scrollTo(0, 0)")
+ assert_no_selector "#sticky-issue-header", text: issue.subject
+ end
+end
diff --git a/test/system/sudo_mode_test.rb b/test/system/sudo_mode_test.rb
index 73e755acd..307d465ff 100644
--- a/test/system/sudo_mode_test.rb
+++ b/test/system/sudo_mode_test.rb
@@ -48,7 +48,6 @@ class SudoModeSystemTest < ApplicationSystemTestCase
find('input[name=commit]').click
end
- assert_equal '/users', current_path
assert page.has_content?("Confirm your password to continue")
assert page.has_css?('form#sudo-form')
@@ -56,6 +55,8 @@ class SudoModeSystemTest < ApplicationSystemTestCase
fill_in 'Password', :with => 'admin'
click_button 'Submit'
end
+
+ assert_text /User johnpaul created./
end
end
diff --git a/test/system/timelog_test.rb b/test/system/timelog_test.rb
index 57c521096..38c3ae19c 100644
--- a/test/system/timelog_test.rb
+++ b/test/system/timelog_test.rb
@@ -49,6 +49,8 @@ class TimelogTest < ApplicationSystemTestCase
select 'QA', :from => 'Activity'
page.first(:button, 'Submit').click
+ assert_text 'Successful update.'
+
entries = TimeEntry.where(:id => [1, 2, 3]).to_a
assert entries.all? {|entry| entry.hours == 8.5}
assert entries.all? {|entry| entry.activity.name == 'QA'}
@@ -89,6 +91,7 @@ class TimelogTest < ApplicationSystemTestCase
select 'Tracker', :from => 'Available Columns'
page.first('input[type=button].move-right').click
click_on 'Save'
+ assert_text 'Successful update.'
# Display the list with updated settings
visit '/time_entries'