diff options
Diffstat (limited to 'test')
23 files changed, 487 insertions, 44 deletions
diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb index 040667c39..38d69e7c8 100644 --- a/test/application_system_test_case.rb +++ b/test/application_system_test_case.rb @@ -72,8 +72,8 @@ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase # Should not depend on locale since Redmine displays login page # using default browser locale which depend on system locale for "real" browsers drivers def log_user(login, password) + visit '/my/page' assert_current_path '/login', :ignore_query => true - assert_equal '/login', current_path within('#login-form form') do fill_in 'username', :with => login fill_in 'password', :with => password diff --git a/test/functional/attachments_controller_test.rb b/test/functional/attachments_controller_test.rb index 04fdb15d2..c2e7e2f7b 100644 --- a/test/functional/attachments_controller_test.rb +++ b/test/functional/attachments_controller_test.rb @@ -42,7 +42,7 @@ class AttachmentsControllerTest < Redmine::ControllerTest assert_response :success assert_equal 'text/html', @response.media_type - assert_select 'th.filename', :text => /issues_controller.rb\t\(révision 1484\)/ + assert_select 'th.filename', :text => /issues_controller\.rb \(révision 1484\)/ assert_select 'td.line-code', :text => /Demande créée avec succès/ end end @@ -61,7 +61,7 @@ class AttachmentsControllerTest < Redmine::ControllerTest assert_response :success assert_equal 'text/html', @response.media_type - assert_select 'th.filename', :text => /issues_controller.rb\t\(r\?vision 1484\)/ + assert_select 'th.filename', :text => /issues_controller\.rb \(r\?vision 1484\)/ assert_select 'td.line-code', :text => /Demande cr\?\?e avec succ\?s/ end end @@ -81,7 +81,7 @@ class AttachmentsControllerTest < Redmine::ControllerTest assert_response :success assert_equal 'text/html', @response.media_type - assert_select 'th.filename', :text => /issues_controller.rb\t\(révision 1484\)/ + assert_select 'th.filename', :text => /issues_controller\.rb \(révision 1484\)/ assert_select 'td.line-code', :text => /Demande créée avec succès/ end end diff --git a/test/functional/documents_controller_test.rb b/test/functional/documents_controller_test.rb index b59ecdc81..944f0b30f 100644 --- a/test/functional/documents_controller_test.rb +++ b/test/functional/documents_controller_test.rb @@ -113,9 +113,9 @@ class DocumentsControllerTest < Redmine::ControllerTest # adds a long description to the first document doc = documents(:documents_001) doc.update(:description => <<~LOREM) - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut egestas, mi vehicula varius varius, ipsum massa fermentum orci, eget tristique ante sem vel mi. Nulla facilisi. Donec enim libero, luctus ac sagittis sit amet, vehicula sagittis magna. Duis ultrices molestie ante, eget scelerisque sem iaculis vitae. Etiam fermentum mauris vitae metus pharetra condimentum fermentum est pretium. Proin sollicitudin elementum quam quis pharetra. Aenean facilisis nunc quis elit volutpat mollis. Aenean eleifend varius euismod. Ut dolor est, congue eget dapibus eget, elementum eu odio. Integer et lectus neque, nec scelerisque nisi. EndOfLineHere + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut egestas, mi vehicula varius varius, ipsum massa fermentum orci, eget tristique ante sem vel mi. Nulla facilisi. Donec enim libero, luctus ac sagittis sit amet, vehicula sagittis magna. Duis ultrices molestie ante, eget scelerisque sem iaculis vitae. Etiam fermentum mauris vitae metus pharetra condimentum fermentum est pretium. Proin sollicitudin elementum quam quis pharetra. Aenean facilisis nunc quis elit volutpat mollis. Aenean eleifend varius euismod. Ut dolor est, congue eget dapibus eget, elementum eu odio. Integer et lectus neque, nec scelerisque nisi. EndOfLineHere - Vestibulum non velit mi. Aliquam scelerisque libero ut nulla fringilla a sollicitudin magna rhoncus. Praesent a nunc lorem, ac porttitor eros. Sed ac diam nec neque interdum adipiscing quis quis justo. Donec arcu nunc, fringilla eu dictum at, venenatis ac sem. Vestibulum quis elit urna, ac mattis sapien. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Vestibulum non velit mi. Aliquam scelerisque libero ut nulla fringilla a sollicitudin magna rhoncus. Praesent a nunc lorem, ac porttitor eros. Sed ac diam nec neque interdum adipiscing quis quis justo. Donec arcu nunc, fringilla eu dictum at, venenatis ac sem. Vestibulum quis elit urna, ac mattis sapien. Lorem ipsum dolor sit amet, consectetur adipiscing elit. LOREM get(:index, :params => {:project_id => 'ecookbook'}) assert_response :success diff --git a/test/functional/issues_controller_test.rb b/test/functional/issues_controller_test.rb index b7e0321d4..48304c868 100644 --- a/test/functional/issues_controller_test.rb +++ b/test/functional/issues_controller_test.rb @@ -1737,7 +1737,7 @@ class IssuesControllerTest < Redmine::ControllerTest assert_select 'td.last_notes[colspan="4"]', :text => 'Some notes with Redmine links: #2, r2.' assert_select( 'td.last_notes[colspan="4"]', - :text => 'A comment with inline image: and a reference to #1 and r2.' + :text => 'A comment with inline image: and a reference to #1 and r2.' ) get( :index, @@ -3347,8 +3347,8 @@ class IssuesControllerTest < Redmine::ControllerTest # The current_user can only see members who belong to projects that the current_user has access to. # Since the Redmine Admin user does not belong to any projects visible to the current_user, # the Redmine Admin user's name is not displayed in the reaction user list. Instead, "1 other" is shown. - assert_select 'a.reaction-button[title=?]', 'Dave Lopper, John Smith, and 1 other' do - assert_select 'span.icon-label', '3' + assert_select 'a.reaction-button[title=?]', 'Dave Lopper and John Smith' do + assert_select 'span.icon-label', '2' end end diff --git a/test/functional/workflows_controller_test.rb b/test/functional/workflows_controller_test.rb index b30559d80..dcdc8d5bb 100644 --- a/test/functional/workflows_controller_test.rb +++ b/test/functional/workflows_controller_test.rb @@ -211,6 +211,45 @@ class WorkflowsControllerTest < Redmine::ControllerTest assert w.assignee end + def test_post_edit_with_large_number_of_statuses + # This test ensures that workflows with many statuses can be saved. + # Without setting `ENV['RACK_QUERY_PARSER_PARAMS_LIMIT']`, this raises + # ActionController::BadRequest exception due to exceeding the default + # query parameter limit of 4096. + WorkflowTransition.delete_all + + num_statuses = 40 + transitions_data = {} + + # Allowed statuses for a new issue (status_id = 0) + transitions_data['0'] = {} + (1..num_statuses).each do |status_id| + transitions_data['0'][status_id.to_s] = {'always' => '1'} + end + + # Status transitions between statuses + (1..num_statuses).each do |status_id_from| # rubocop:disable RuboCopStyle/CombinableLoops + transitions_data[status_id_from.to_s] = {} + (1..num_statuses).each do |status_id_to| + # skip self-transitions + next if status_id_from == status_id_to + + transitions_data[status_id_from.to_s][status_id_to.to_s] = { + 'always' => '1', 'author' => '1', 'assignee' => '1' + } + end + end + + assert_nothing_raised do + patch :update, :params => { + :role_id => 2, + :tracker_id => 1, + :transitions => transitions_data + } + end + assert_response :found + end + def test_get_permissions get :permissions diff --git a/test/helpers/application_helper_test.rb b/test/helpers/application_helper_test.rb index f959744e2..2e2e8b933 100644 --- a/test/helpers/application_helper_test.rb +++ b/test/helpers/application_helper_test.rb @@ -1732,6 +1732,46 @@ class ApplicationHelperTest < Redmine::HelperTest end end + def test_section_edit_links_with_multiline_heading + raw = <<~RAW + # Wiki + + ## `Foo` Bar + + The heading above generates multiline HTML. + Don't assume heading tags are always single-line. + + ``` + <h2> + <code>Foo</code> Bar</h2> + ``` + RAW + @project = Project.find(1) + set_language_if_valid 'en' + with_settings :text_formatting => 'common_mark' do + result = + textilizable( + raw, + :edit_section_links => + {:controller => 'wiki', :action => 'edit', + :project_id => '1', :id => 'Test'} + ).delete("\n") + + assert_match( + Regexp.new( + '<div class="contextual heading-2" title="Edit this section" id="section-2">' \ + '<a class="icon-only icon-edit" href="/projects/1/wiki/Test/edit\?section=2">' \ + '<svg class="s18 icon-svg" aria-hidden="true"><use href="/assets/icons-.*\.svg#icon--edit"></use></svg>' \ + '<span class="icon-label">Edit this section</span>' \ + '</a></div>' \ + '<a name="Foo-Bar"></a>' \ + '<h2 ><code>Foo</code> Bar<a href="#Foo-Bar" class="wiki-anchor">¶</a></h2>' + ), + result + ) + end + end + def test_default_formatter with_settings :text_formatting => 'unknown' do text = 'a *link*: http://www.example.net/' @@ -2363,6 +2403,14 @@ class ApplicationHelperTest < Redmine::HelperTest assert_equal expected, format_activity_description(text) end + def test_render_flash_messages_should_ignore_non_string_values + flash[:array_value] = ['1', '2'] + flash[:hash_value] = { foo: 'bar' } + + result = render_flash_messages + assert_equal '', result + end + private def wiki_links_with_special_characters diff --git a/test/helpers/avatars_helper_test.rb b/test/helpers/avatars_helper_test.rb index f407ae09e..baa64a653 100644 --- a/test/helpers/avatars_helper_test.rb +++ b/test/helpers/avatars_helper_test.rb @@ -68,6 +68,18 @@ class AvatarsHelperTest < Redmine::HelperTest assert_include 'class="gravatar picture"', avatar('jsmith <jsmith@somenet.foo>', :class => 'picture') end + def test_avatar_with_initials + with_settings :gravatar_default => 'initials' do + assert_include 'initials="RA"', avatar(User.find(1)) + end + end + + def test_avatar_should_reject_initials_if_default_is_not_initials + with_settings :gravatar_default => 'identicon' do + assert_not_include 'initials="RA"', avatar(User.find(1)) + end + end + def test_avatar_disabled with_settings :gravatar_enabled => '0' do assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo')) diff --git a/test/helpers/icons_helper_test.rb b/test/helpers/icons_helper_test.rb index ab0b58db4..7ef071f86 100644 --- a/test/helpers/icons_helper_test.rb +++ b/test/helpers/icons_helper_test.rb @@ -71,6 +71,13 @@ class IconsHelperTest < Redmine::HelperTest assert_match expected, icon end + def test_sprite_icon_should_return_svg_with_filled_class_when_style_is_filled + expected = %r{<svg class="s18 icon-svg icon-svg-filled" aria-hidden="true"><use href="/assets/icons-\w+.svg#icon--edit"></use></svg>$} + icon = sprite_icon('edit', style: :filled) + + assert_match expected, icon + end + def test_file_icon_should_return_folder_icon_for_directory entry = stub(:is_dir? => true) expected = %r{<svg class="s18 icon-svg" aria-hidden="true"><use href="/assets/icons-\w+.svg#icon--folder"></use></svg><span class="icon-label">folder_name</span>} diff --git a/test/helpers/journals_helper_test.rb b/test/helpers/journals_helper_test.rb index 355d5ec6f..47f7b7749 100644 --- a/test/helpers/journals_helper_test.rb +++ b/test/helpers/journals_helper_test.rb @@ -47,10 +47,27 @@ class JournalsHelperTest < Redmine::HelperTest journals = issue.visible_journals_with_index # add indice journal_actions = render_journal_actions(issue, journals.first, {reply_links: true}) - assert_select_in journal_actions, 'a[title=?][class="icon icon-comment"]', 'Quote' + assert_select_in journal_actions, 'a[title=?][class="icon icon-quote"]', 'Quote' assert_select_in journal_actions, 'a[title=?][class="icon-only icon-edit"]', 'Edit' assert_select_in journal_actions, 'div[class="drdn-items"] a[class="icon icon-del"]' assert_select_in journal_actions, 'div[class="drdn-items"] a[class="icon icon-copy-link"]' + assert_select_in journal_actions, 'span.reaction-button-wrapper' + end + + def test_render_journal_actions_with_journal_without_notes + User.current = User.find(1) + issue = Issue.find(1) + issue.journals.first.update!(notes: '') + + journals = issue.visible_journals_with_index + + journal_actions = render_journal_actions(issue, journals.first, reply_links: true) + + assert_select_in journal_actions, 'span.reaction-button-wrapper' + assert_select_in journal_actions, 'span.drdn' + + assert_select_in journal_actions, 'a[class="icon-comment"]', false + assert_select_in journal_actions, 'a[class="icon-edit"]', false end def test_journal_thumbnail_attachments_should_be_in_the_same_order_as_the_journal_details diff --git a/test/helpers/reactions_helper_test.rb b/test/helpers/reactions_helper_test.rb index f3a4e38d8..1c5c82418 100644 --- a/test/helpers/reactions_helper_test.rb +++ b/test/helpers/reactions_helper_test.rb @@ -106,12 +106,30 @@ class ReactionsHelperTest < ActionView::TestCase assert_select_in result, 'a.reaction-button[title=?]', expected_tooltip end - test 'reaction_button displays non-visible users as "X other" in the tooltip' do + test 'reaction_button should be label less when no reactions' do + issue = issues(:issues_002) + + result = with_locale('en') do + reaction_button(issue) + end + assert_select_in result, 'a.reaction-button' do + assert_select 'span.icon-label', false + end + + # readonly + User.current = nil + result = with_locale('en') do + reaction_button(issue) + end + assert_select_in result, 'span.reaction-button.readonly' do + assert_select 'span.icon-label', false + end + end + + test 'reaction_button should not count and display non-visible users' do issue2 = issues(:issues_002) issue2.reaction_detail = Reaction::Detail.new( - # The remaining 3 users are non-visible users - reaction_count: 5, visible_users: users(:users_002, :users_003) ) @@ -119,11 +137,10 @@ class ReactionsHelperTest < ActionView::TestCase reaction_button(issue2) end - assert_select_in result, 'a.reaction-button[title=?]', 'John Smith, Dave Lopper, and 3 others' + assert_select_in result, 'a.reaction-button[title=?]', 'John Smith and Dave Lopper' # When all users are non-visible users issue2.reaction_detail = Reaction::Detail.new( - reaction_count: 2, visible_users: [] ) @@ -131,7 +148,10 @@ class ReactionsHelperTest < ActionView::TestCase reaction_button(issue2) end - assert_select_in result, 'a.reaction-button[title=?]', '2 others' + assert_select_in result, 'a.reaction-button[title]', false + assert_select_in result, 'a.reaction-button' do + assert_select 'span.icon-label', false + end end test 'reaction_button formats the tooltip content based on the support.array settings of each locale' do @@ -152,7 +172,7 @@ class ReactionsHelperTest < ActionView::TestCase end tooltip = 'Dave Lopper, John Smith, and Redmine Admin' - assert_select_in result, 'span[data-reaction-button-id=?]', 'reaction_issue_1' do + assert_select_in result, 'span.reaction-button-wrapper[data-reaction-button-id=?]', 'reaction_issue_1' do href = reaction_path(issue.reaction_detail.user_reaction, object_type: 'Issue', object_id: 1) assert_select 'a.icon.reaction-button.reacted[href=?]', href do @@ -174,7 +194,7 @@ class ReactionsHelperTest < ActionView::TestCase end tooltip = 'Dave Lopper, John Smith, and Redmine Admin' - assert_select_in result, 'span[data-reaction-button-id=?]', 'reaction_issue_1' do + assert_select_in result, 'span.reaction-button-wrapper[data-reaction-button-id=?]', 'reaction_issue_1' do href = reactions_path(object_type: 'Issue', object_id: 1) assert_select 'a.icon.reaction-button[href=?]', href do diff --git a/test/integration/api_test/news_test.rb b/test/integration/api_test/news_test.rb index bd9f2bb6d..399b2b347 100644 --- a/test/integration/api_test/news_test.rb +++ b/test/integration/api_test/news_test.rb @@ -62,7 +62,7 @@ class Redmine::ApiTest::NewsTest < Redmine::ApiTest::Base assert_select "author[id=2][name=\"John Smith\"]" assert_select 'title', 'eCookbook first release !' assert_select 'summary', 'First version was released...' - assert_select 'description', "eCookbook 1.0 has been released.\n\nVisit http://ecookbook.somenet.foo/" + assert_select 'description', 'eCookbook 1.0 has been released. Visit http://ecookbook.somenet.foo/' assert_select 'created_on', News.find(1).created_on.iso8601 end 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 index 01ba76832..96dd4cf81 100644 --- a/test/system/reactions_test.rb +++ b/test/system/reactions_test.rb @@ -113,6 +113,47 @@ class ReactionsSystemTest < ApplicationSystemTestCase 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) @@ -126,7 +167,7 @@ class ReactionsSystemTest < ApplicationSystemTestCase # Remove the reaction within(reaction_button) { find('a.reacted').click } within(reaction_button) { assert_selector('a.reaction-button:not(.reacted)') } - assert_equal "0", reaction_button.text + assert_equal "", reaction_button.text assert_equal 0, expected_subject.reactions.count end end diff --git a/test/unit/lib/redmine/field_format/progressbar_format_test.rb b/test/unit/lib/redmine/field_format/progressbar_format_test.rb index 51bd8bc5f..6e0df724d 100644 --- a/test/unit/lib/redmine/field_format/progressbar_format_test.rb +++ b/test/unit/lib/redmine/field_format/progressbar_format_test.rb @@ -116,5 +116,17 @@ module Redmine::FieldFormat end end end + + def test_formatted_value_with_html_true + expected = progress_bar(50) + formatted = @format.formatted_value(self, @field, 50, Issue.new, true) + assert_equal expected, formatted + assert formatted.html_safe? + end + + def test_formatted_value_with_html_false + formatted = @format.formatted_value(self, @field, 50, Issue.new, false) + assert_equal '50', formatted + end end end diff --git a/test/unit/lib/redmine/quote_reply_helper_test.rb b/test/unit/lib/redmine/quote_reply_helper_test.rb index 43adb521b..cbac1f6d0 100644 --- a/test/unit/lib/redmine/quote_reply_helper_test.rb +++ b/test/unit/lib/redmine/quote_reply_helper_test.rb @@ -29,7 +29,7 @@ class QuoteReplyHelperTest < ActionView::TestCase a_tag = quote_reply(url, '#issue_description_wiki') assert_includes a_tag, %|onclick="#{h "quoteReply('/issues/1/quoted', '#issue_description_wiki', 'common_mark'); return false;"}"| - assert_includes a_tag, %|class="icon icon-comment"| + assert_includes a_tag, %|class="icon icon-quote"| assert_not_includes a_tag, 'title=' # When icon_only is true diff --git a/test/unit/lib/redmine/reaction_test.rb b/test/unit/lib/redmine/reaction_test.rb index bed4600d0..f3228a3bd 100644 --- a/test/unit/lib/redmine/reaction_test.rb +++ b/test/unit/lib/redmine/reaction_test.rb @@ -42,7 +42,6 @@ class Redmine::ReactionTest < ActiveSupport::TestCase Issue.preload_reaction_details([issue1, issue2]) expected_issue1_reaction_detail = Reaction::Detail.new( - reaction_count: 3, visible_users: [users(:users_003), users(:users_002), users(:users_001)], user_reaction: reactions(:reaction_002) ) @@ -53,7 +52,6 @@ class Redmine::ReactionTest < ActiveSupport::TestCase # Even when an object has no reactions, an empty ReactionDetail is set. assert_equal Reaction::Detail.new( - reaction_count: 0, visible_users: [], user_reaction: nil ), issue2.reaction_detail @@ -107,7 +105,6 @@ class Redmine::ReactionTest < ActiveSupport::TestCase assert_nil message7.instance_variable_get(:@reaction_detail) assert_equal Reaction::Detail.new( - reaction_count: 1, visible_users: [users(:users_002)], user_reaction: reactions(:reaction_009) ), message7.reaction_detail @@ -122,7 +119,6 @@ class Redmine::ReactionTest < ActiveSupport::TestCase comment1.load_reaction_detail assert_equal Reaction::Detail.new( - reaction_count: 1, visible_users: [users(:users_002)], user_reaction: nil ), comment1.reaction_detail @@ -153,7 +149,7 @@ class Redmine::ReactionTest < ActiveSupport::TestCase assert_not Redmine::Reaction.visible?(object, user) end - test 'writable? returns true for various reactable objects when user is logged in, object is visible, and project is active' do + test 'editable? returns true for various reactable objects when user is logged in, object is visible, and project is active' do reactable_objects = { issue: issues(:issues_007), message: messages(:messages_001), @@ -164,30 +160,30 @@ class Redmine::ReactionTest < ActiveSupport::TestCase user = users(:users_002) reactable_objects.each do |type, object| - assert Redmine::Reaction.writable?(object, user), "Expected writable? to return true for #{type}" + assert Redmine::Reaction.editable?(object, user), "Expected editable? to return true for #{type}" end end - test 'writable? returns false when user is not logged in' do + test 'editable? returns false when user is not logged in' do object = issues(:issues_007) user = User.anonymous - assert_not Redmine::Reaction.writable?(object, user) + assert_not Redmine::Reaction.editable?(object, user) end - test 'writable? returns false when project is inactive' do + test 'editable? returns false when project is inactive' do object = issues(:issues_007) user = users(:users_002) object.project.update!(status: Project::STATUS_ARCHIVED) - assert_not Redmine::Reaction.writable?(object, user) + assert_not Redmine::Reaction.editable?(object, user) end - test 'writable? returns false when project is closed' do + test 'editable? returns false when project is closed' do object = issues(:issues_007) user = users(:users_002) object.project.update!(status: Project::STATUS_CLOSED) - assert_not Redmine::Reaction.writable?(object, user) + assert_not Redmine::Reaction.editable?(object, user) end end diff --git a/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb b/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb index d9a84a2c2..bb0c5d450 100644 --- a/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb +++ b/test/unit/lib/redmine/wiki_formatting/common_mark/formatter_test.rb @@ -226,7 +226,7 @@ class Redmine::WikiFormatting::CommonMark::FormatterTest < ActionView::TestCase text = STR_WITH_PRE.join("\n\n") replacement = "New text" - assert_equal [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"), + assert_equal [STR_WITH_PRE[0..1], "New text"].join("\n\n"), @formatter.new(text).update_section(3, replacement) end @@ -319,7 +319,11 @@ class Redmine::WikiFormatting::CommonMark::FormatterTest < ActionView::TestCase html = to_html(text) %w[note tip warning caution important].each do |alert| - assert_include "<div class=\"markdown-alert markdown-alert-note\">\n<p class=\"markdown-alert-title\">Note</p>\n<p>This is a note.</p>\n</div>", html + icon = Redmine::WikiFormatting::CommonMark::ALERT_TYPE_TO_ICON_NAME[alert] + # rubocop:disable Layout/LineLength + expected = %r{<div class="markdown-alert markdown-alert-#{alert}">\n<p class="markdown-alert-title"><svg class="s18 icon-svg" aria-hidden="true"><use href="/assets/icons-\w+.svg\#icon--#{icon}"></use></svg><span class="icon-label">#{alert.capitalize}</span></p>\n<p>This is a #{alert}.</p>\n</div>} + # rubocop:enable Layout/LineLength + assert_match expected, html end end diff --git a/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb b/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb index 32280cfdf..678d4c6b2 100644 --- a/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb +++ b/test/unit/lib/redmine/wiki_formatting/textile_formatter_test.rb @@ -466,19 +466,19 @@ class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase replacement = "New text" assert_equal( - [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"), + [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement) ) assert_equal( - [STR_WITHOUT_PRE[0..1], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), + [STR_WITHOUT_PRE[0..1], replacement, STR_WITHOUT_PRE[4]].join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(3, replacement) ) assert_equal( - [STR_WITHOUT_PRE[0..2], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), + [STR_WITHOUT_PRE[0..2], replacement, STR_WITHOUT_PRE[4]].join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(5, replacement) ) assert_equal( - [STR_WITHOUT_PRE[0..3], replacement].flatten.join("\n\n"), + [STR_WITHOUT_PRE[0..3], replacement].join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(6, replacement) ) assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(0, replacement) @@ -488,7 +488,7 @@ class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase def test_update_section_with_hash_should_update_the_requested_section replacement = "New text" assert_equal( - [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"), + [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE). update_section(2, replacement, ActiveSupport::Digest.hexdigest(STR_WITHOUT_PRE[1])) ) @@ -552,7 +552,7 @@ class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase text = STR_WITH_PRE.join("\n\n") replacement = "New text" assert_equal( - [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"), + [STR_WITH_PRE[0..1], "New text"].join("\n\n"), @formatter.new(text).update_section(3, replacement) ) end diff --git a/test/unit/member_test.rb b/test/unit/member_test.rb index 42fba4783..df9088027 100644 --- a/test/unit/member_test.rb +++ b/test/unit/member_test.rb @@ -108,7 +108,7 @@ class MemberTest < ActiveSupport::TestCase assert !member.save assert_include I18n.translate('activerecord.errors.messages.empty'), member.errors[:role] assert_equal 'Rôle doit être renseigné(e)', - [member.errors.full_messages].flatten.join + [member.errors.full_messages].join end def test_validate_member_role diff --git a/test/unit/reaction_test.rb b/test/unit/reaction_test.rb index 2690da351..9b3da0738 100644 --- a/test/unit/reaction_test.rb +++ b/test/unit/reaction_test.rb @@ -75,12 +75,10 @@ class ReactionTest < ActiveSupport::TestCase expected = { 1 => Reaction::Detail.new( - reaction_count: 3, visible_users: [users(:users_003), users(:users_002), users(:users_001)], user_reaction: reactions(:reaction_003) ), 6 => Reaction::Detail.new( - reaction_count: 1, visible_users: [users(:users_002)], user_reaction: nil ) diff --git a/test/unit/role_test.rb b/test/unit/role_test.rb index 21103919f..1d0d39d7e 100644 --- a/test/unit/role_test.rb +++ b/test/unit/role_test.rb @@ -175,6 +175,32 @@ class RoleTest < ActiveSupport::TestCase assert_equal false, role.permissions_tracker_ids?(:view_issues, 1) end + def test_allowed_to_with_symbol + role = Role.create!(:name => 'Test', :permissions => [:view_issues]) + assert_equal true, role.allowed_to?(:view_issues) + assert_equal false, role.allowed_to?(:add_issues) + end + + def test_allowed_to_with_symbol_and_scope + role = Role.create!(:name => 'Test', :permissions => [:view_issues, :delete_issues]) + assert_equal true, role.allowed_to?(:view_issues, [:view_issues, :add_issues]) + assert_equal false, role.allowed_to?(:add_issues, [:view_issues, :add_issues]) + assert_equal false, role.allowed_to?(:delete_issues, [:view_issues, :add_issues]) + end + + def test_allowed_to_with_hash + role = Role.create!(:name => 'Test', :permissions => [:view_issues]) + assert_equal true, role.allowed_to?(:controller => 'issues', :action => 'show') + assert_equal false, role.allowed_to?(:controller => 'issues', :action => 'create') + end + + def test_allowed_to_with_hash_and_scope + role = Role.create!(:name => 'Test', :permissions => [:view_issues, :delete_issues]) + assert_equal true, role.allowed_to?({:controller => 'issues', :action => 'show'}, [:view_issues, :add_issues]) + assert_equal false, role.allowed_to?({:controller => 'issues', :action => 'create'}, [:view_issues, :add_issues]) + assert_equal false, role.allowed_to?({:controller => 'issues', :action => 'destroy'}, [:view_issues, :add_issues]) + end + def test_has_permission_without_permissions role = Role.create!(:name => 'Test') assert_equal false, role.has_permission?(:delete_issues) diff --git a/test/unit/setting_test.rb b/test/unit/setting_test.rb index 4ae07cebb..cbfabbb02 100644 --- a/test/unit/setting_test.rb +++ b/test/unit/setting_test.rb @@ -147,4 +147,8 @@ class SettingTest < ActiveSupport::TestCase def test_default_text_formatting_for_new_installations_is_common_mark assert_equal 'common_mark', Setting.text_formatting end + + def test_default_wiki_tablesort_enabled_for_new_installations_is_disabled + assert_equal "0", Setting.wiki_tablesort_enabled + end end diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index aeae62df8..967771c87 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -589,6 +589,27 @@ class UserTest < ActiveSupport::TestCase end end + def test_initials_format + assert_equal 'JS', @jsmith.initials(:firstname_lastinitial) + assert_equal 'SJ', @jsmith.initials(:lastname_comma_firstname) + assert_equal 'SJ', @jsmith.initials(:lastname_firstname) + assert_equal 'JS', @jsmith.initials(:firstinitial_lastname) + assert_equal 'JL', User.new(:firstname => 'Jean-Philippe', :lastname => 'Lang').initials(:firstinitial_lastname) + assert_equal 'JS', @jsmith.initials(:undefined_format) + end + + def test_initials_should_use_setting_as_default_format + with_settings :user_format => :firstname_lastname do + assert_equal 'JS', @jsmith.reload.initials + end + with_settings :user_format => :username do + assert_equal 'JS', @jsmith.reload.initials + end + with_settings :user_format => :lastname do + assert_equal 'SM', @jsmith.reload.initials + end + end + def test_lastname_should_accept_255_characters u = User.first u.lastname = 'a' * 255 @@ -1377,6 +1398,67 @@ class UserTest < ActiveSupport::TestCase end end + def test_should_recognize_authorized_by_oauth + u = User.find 2 + assert_not u.authorized_by_oauth? + u.oauth_scope = [:add_issues, :view_issues] + assert u.authorized_by_oauth? + end + + def test_admin_should_be_limited_by_oauth_scope + u = User.find_by_admin(true) + assert u.admin? + + u.oauth_scope = [:add_issues, :view_issues] + assert_not u.admin? + + u.oauth_scope = [:add_issues, :view_issues, :admin] + assert u.admin? + + u = User.find_by_admin(false) + assert_not u.admin? + u.oauth_scope = [:add_issues, :view_issues, :admin] + assert_not u.admin? + end + + def test_oauth_scope_should_limit_global_user_permissions + admin = User.find 1 + user = User.find 2 + [admin, user].each do |u| + assert u.allowed_to?(:add_issues, nil, global: true) + assert u.allowed_to?(:view_issues, nil, global: true) + u.oauth_scope = [:view_issues] + assert_not u.allowed_to?(:add_issues, nil, global: true) + assert u.allowed_to?(:view_issues, nil, global: true) + end + end + + def test_oauth_scope_should_limit_project_user_permissions + admin = User.find 1 + project = Project.find 5 + assert admin.allowed_to?(:add_issues, project) + assert admin.allowed_to?(:view_issues, project) + admin.oauth_scope = [:view_issues] + assert_not admin.allowed_to?(:add_issues, project) + assert admin.allowed_to?(:view_issues, project) + + admin.oauth_scope = [:view_issues, :admin] + assert admin.allowed_to?(:add_issues, project) + assert admin.allowed_to?(:view_issues, project) + + user = User.find 2 + project = Project.find 1 + assert user.allowed_to?(:add_issues, project) + assert user.allowed_to?(:view_issues, project) + user.oauth_scope = [:view_issues] + assert_not user.allowed_to?(:add_issues, project) + assert user.allowed_to?(:view_issues, project) + + user.oauth_scope = [:view_issues, :admin] + assert_not user.allowed_to?(:add_issues, project) + assert user.allowed_to?(:view_issues, project) + end + def test_destroy_should_delete_associated_reactions users(:users_004).reactions.create!( [ |