diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index e2054525de57..74ffad708a47 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -11,3 +11,4 @@ f3c99ee5dded81ad55f2b6f3706216d5fa765677 9e4934cd0a468f46d8f0fc0f11ebc2d4216f789c 6678cab48d443b5782fa93b171d62093819ee4fc fa5d03eae00bc8931f99598a74ffd76e0cbca3da +b10e6d718cc49e3574837d97fab268e3ecb3fcbd diff --git a/app/components/admin/attachments_settings_header_component.rb b/app/components/admin/attachments_settings_header_component.rb index f9a955648a2e..88d13b0c1808 100644 --- a/app/components/admin/attachments_settings_header_component.rb +++ b/app/components/admin/attachments_settings_header_component.rb @@ -31,7 +31,8 @@ module Admin class AttachmentsSettingsHeaderComponent < ApplicationComponent def initialize(title:, selected:) - raise 'selected must 1, 2 or 3' if [1, 2, 3].exclude?(selected) + raise "selected must 1, 2 or 3" if [1, 2, 3].exclude?(selected) + @title = title @selected = selected end diff --git a/app/helpers/frontend_asset_helper.rb b/app/helpers/frontend_asset_helper.rb index 9adfd5dbefda..3d1d30b91765 100644 --- a/app/helpers/frontend_asset_helper.rb +++ b/app/helpers/frontend_asset_helper.rb @@ -27,14 +27,14 @@ #++ module FrontendAssetHelper - CLI_DEFAULT_PROXY = 'http://localhost:4200'.freeze + CLI_DEFAULT_PROXY = "http://localhost:4200".freeze def self.assets_proxied? - ENV['OPENPROJECT_DISABLE_DEV_ASSET_PROXY'].blank? && !Rails.env.production? && cli_proxy.present? + ENV["OPENPROJECT_DISABLE_DEV_ASSET_PROXY"].blank? && !Rails.env.production? && cli_proxy.present? end def self.cli_proxy - ENV.fetch('OPENPROJECT_CLI_PROXY', CLI_DEFAULT_PROXY) + ENV.fetch("OPENPROJECT_CLI_PROXY", CLI_DEFAULT_PROXY) end ## diff --git a/app/models/project.rb b/app/models/project.rb index dbb53cbdefc6..1bb82198272f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -40,7 +40,6 @@ class Project < ApplicationRecord include ::Scopes::Scoped - # Maximum length for project identifiers IDENTIFIER_MAX_LENGTH = 100 diff --git a/app/models/setting.rb b/app/models/setting.rb index 749ce4dfbf44..0d885dd16a17 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -133,7 +133,7 @@ def respond_to_missing?(method_name, include_private = false) private def accessor_base_name(name) - name.to_s.sub(/(_writable\?)|(\?)|=\z/, '') + name.to_s.sub(/(_writable\?)|(\?)|=\z/, "") end end @@ -337,7 +337,7 @@ def self.deserialize(name, value) if definition.serialized? && value.is_a?(String) deserialize_hash(value) - elsif value != ''.freeze && !value.nil? + elsif value != "".freeze && !value.nil? read_formatted_setting(value, definition.format) else definition.format == :string ? value : nil diff --git a/app/models/work_package/exports/macros/attributes.rb b/app/models/work_package/exports/macros/attributes.rb index 8b50adfa503e..d8b30f793406 100644 --- a/app/models/work_package/exports/macros/attributes.rb +++ b/app/models/work_package/exports/macros/attributes.rb @@ -77,16 +77,16 @@ def self.resolve_match(type, model_s, id, attribute, work_package, user) elsif model_s == "project" resolve_project_match(id || work_package.project.id, type, attribute, user) else - msg_macro_error I18n.t('export.macro.model_not_found', model: model_s) + msg_macro_error I18n.t("export.macro.model_not_found", model: model_s) end end def self.msg_macro_error(message) - msg_inline I18n.t('export.macro.error', message:) + msg_inline I18n.t("export.macro.error", message:) end def self.msg_macro_error_rich_text - msg_inline I18n.t('export.macro.rich_text_unsupported') + msg_inline I18n.t("export.macro.rich_text_unsupported") end def self.msg_inline(message) @@ -109,11 +109,11 @@ def self.resolve_label(model, attribute) def self.resolve_work_package_match(id, type, attribute, user) return resolve_label_work_package(attribute) if type == "label" - return msg_macro_error(I18n.t('export.macro.model_not_found', model: type)) unless type == "value" + return msg_macro_error(I18n.t("export.macro.model_not_found", model: type)) unless type == "value" work_package = WorkPackage.visible(user).find_by(id:) if work_package.nil? - return msg_macro_error(I18n.t('export.macro.resource_not_found', resource: "#{WorkPackage.name} #{id}")) + return msg_macro_error(I18n.t("export.macro.resource_not_found", resource: "#{WorkPackage.name} #{id}")) end resolve_value_work_package(work_package, attribute) diff --git a/app/services/projects/copy_service.rb b/app/services/projects/copy_service.rb index 9983adeb566a..72c3990f3a98 100644 --- a/app/services/projects/copy_service.rb +++ b/app/services/projects/copy_service.rb @@ -99,8 +99,9 @@ def after_perform(call) end def copy_activated_custom_fields(call) - call.result.project_custom_field_ids = source.project_custom_field_ids + call.result.project_custom_field_ids = source.project_custom_field_ids end + def contract_options { copy_source: source, validate_model: true } end diff --git a/app/services/users/change_password_service.rb b/app/services/users/change_password_service.rb index b6ccf84b0a29..b2f5c41f7abc 100644 --- a/app/services/users/change_password_service.rb +++ b/app/services/users/change_password_service.rb @@ -65,7 +65,7 @@ def call(params) def invalidate_tokens ::Users::DropTokensService - .new(current_user: current_user) + .new(current_user:) .call! end diff --git a/app/services/users/drop_tokens_service.rb b/app/services/users/drop_tokens_service.rb index 098f397e9ad2..56f79cb75c1f 100644 --- a/app/services/users/drop_tokens_service.rb +++ b/app/services/users/drop_tokens_service.rb @@ -46,11 +46,11 @@ def call!(clear_invitation_tokens: true) private def invalidate_recovery_tokens - Token::Recovery.where(user: user).delete_all + Token::Recovery.where(user:).delete_all end def invalidate_invitation_tokens - Token::Invitation.where(user: user).delete_all + Token::Invitation.where(user:).delete_all end end end diff --git a/db/migrate/20221115082403_add_ldap_tls_options.rb b/db/migrate/20221115082403_add_ldap_tls_options.rb index ef5dbb5d6c2e..862b5305e46c 100644 --- a/db/migrate/20221115082403_add_ldap_tls_options.rb +++ b/db/migrate/20221115082403_add_ldap_tls_options.rb @@ -42,7 +42,7 @@ def change # Current LDAP library default is to not verify the certificate MigratingAuthSource.reset_column_information - ldap_settings = Setting.find_by(name: 'ldap_tls_options')&.value + ldap_settings = Setting.find_by(name: "ldap_tls_options")&.value migrate_ldap_settings(ldap_settings) end end @@ -54,7 +54,7 @@ def migrate_ldap_settings(ldap_settings) return if ldap_settings.blank? parsed = Setting.deserialize_hash(ldap_settings) - verify_peer = parsed['verify_mode'] == OpenSSL::SSL::VERIFY_PEER + verify_peer = parsed["verify_mode"] == OpenSSL::SSL::VERIFY_PEER MigratingAuthSource.update_all(verify_peer:) rescue StandardError => e diff --git a/db/migrate/20240408132459_rename_delay_to_lag.rb b/db/migrate/20240408132459_rename_delay_to_lag.rb index 969c2eefbae5..386790aefb83 100644 --- a/db/migrate/20240408132459_rename_delay_to_lag.rb +++ b/db/migrate/20240408132459_rename_delay_to_lag.rb @@ -3,6 +3,6 @@ def change rename_column :relations, :delay, :lag # TODO remove after 14.0 - add_column :relations, :delay, :virtual, type: :integer, as: 'lag', stored: true + add_column :relations, :delay, :virtual, type: :integer, as: "lag", stored: true end end diff --git a/db/migrate/20240410060041_remove_virtual_delay_column.rb b/db/migrate/20240410060041_remove_virtual_delay_column.rb index 69c75e4083dd..5fc36f3cd66a 100644 --- a/db/migrate/20240410060041_remove_virtual_delay_column.rb +++ b/db/migrate/20240410060041_remove_virtual_delay_column.rb @@ -1,5 +1,5 @@ class RemoveVirtualDelayColumn < ActiveRecord::Migration[7.1] def change - remove_column :relations, :delay, :virtual, type: :integer, as: 'lag', stored: true + remove_column :relations, :delay, :virtual, type: :integer, as: "lag", stored: true end end diff --git a/lib/primer/open_project/forms/dsl/project_autocompleter_input.rb b/lib/primer/open_project/forms/dsl/project_autocompleter_input.rb index 5b58c0ba542f..4c43d5fcd143 100644 --- a/lib/primer/open_project/forms/dsl/project_autocompleter_input.rb +++ b/lib/primer/open_project/forms/dsl/project_autocompleter_input.rb @@ -9,7 +9,7 @@ def derive_autocompleter_options(options) options.reverse_merge!( component: "opce-project-autocompleter", defaultData: false, - filters: [{ name: 'active', operator: '=', values: ['t'] }], + filters: [{ name: "active", operator: "=", values: ["t"] }] ) if options[:disabledProjects] diff --git a/lib_static/plugins/acts_as_journalized/lib/acts/journalized/journable_differ.rb b/lib_static/plugins/acts_as_journalized/lib/acts/journalized/journable_differ.rb index 51ae9205edfd..35f9c13a5f3e 100644 --- a/lib_static/plugins/acts_as_journalized/lib/acts/journalized/journable_differ.rb +++ b/lib_static/plugins/acts_as_journalized/lib/acts/journalized/journable_differ.rb @@ -42,7 +42,7 @@ def association_changes(original, changed, *) get_association_changes(original, changed, *) end - def association_changes_multiple_attributes(original, changed, association, association_name, key, values) + def association_changes_multiple_attributes(original, changed, association, association_name, key, values) list = {} values.each do |value| list.store(value, get_association_changes(original, changed, association, association_name, key, value)) @@ -69,7 +69,7 @@ def normalize_newlines(data) def no_nil_to_empty_strings?(normalized_old_data, attribute, new_value) old_value = normalized_old_data[attribute] - new_value != old_value && ([new_value, old_value] - ['', nil]).present? + new_value != old_value && ([new_value, old_value] - ["", nil]).present? end def journaled_attributes(object) @@ -133,7 +133,7 @@ def select_and_combine_journals(journals, id, key, value) if selected_journals.empty? nil else - selected_journals.sort.join(',') + selected_journals.sort.join(",") end end end diff --git a/lib_static/plugins/acts_as_journalized/lib/acts_as_journalized.rb b/lib_static/plugins/acts_as_journalized/lib/acts_as_journalized.rb index 0c5862d6362c..016922887d68 100644 --- a/lib_static/plugins/acts_as_journalized/lib/acts_as_journalized.rb +++ b/lib_static/plugins/acts_as_journalized/lib/acts_as_journalized.rb @@ -45,14 +45,14 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -require 'journal_changes' -require 'journal_formatter' -require 'cause_of_change' +require "journal_changes" +require "journal_formatter" +require "cause_of_change" module Acts end -Dir[File.expand_path('acts/journalized/*.rb', __dir__)].sort.each { |f| require f } +Dir[File.expand_path("acts/journalized/*.rb", __dir__)].sort.each { |f| require f } module Acts module Journalized diff --git a/lib_static/plugins/acts_as_journalized/lib/cause_of_change.rb b/lib_static/plugins/acts_as_journalized/lib/cause_of_change.rb index c7294d844ce5..0202fe10dead 100644 --- a/lib_static/plugins/acts_as_journalized/lib/cause_of_change.rb +++ b/lib_static/plugins/acts_as_journalized/lib/cause_of_change.rb @@ -45,8 +45,8 @@ # 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 'cause_of_change/base' -require_relative 'cause_of_change/no_cause' +require_relative "cause_of_change/base" +require_relative "cause_of_change/no_cause" module CauseOfChange end diff --git a/modules/calendar/spec/features/calendar_widget_spec.rb b/modules/calendar/spec/features/calendar_widget_spec.rb index 29d9f0fedf47..da3a483d7359 100644 --- a/modules/calendar/spec/features/calendar_widget_spec.rb +++ b/modules/calendar/spec/features/calendar_widget_spec.rb @@ -65,15 +65,14 @@ overview_page.expect_and_dismiss_toaster message: I18n.t("js.notice_successful_update") end - it 'shows the meeting' do - expect(page).to have_css('.fc-event', text: "Weekly", visible: :all) - page.find('.fc-event', text: "Weekly", visible: :all).click + it "shows the meeting" do + expect(page).to have_css(".fc-event", text: "Weekly", visible: :all) + page.find(".fc-event", text: "Weekly", visible: :all).click expect(page).to have_current_path /meetings\/#{meeting.id}/ end it "opens the work package full view when clicking a calendar entry" do - # Clicking the calendar entry goes to work package full screen page.find(".fc-event-title", text: work_package.subject).click wp_full_view.ensure_page_loaded diff --git a/modules/meeting/app/forms/meeting/title.rb b/modules/meeting/app/forms/meeting/title.rb index 8df8e0deb5ea..801c3d84a8fe 100644 --- a/modules/meeting/app/forms/meeting/title.rb +++ b/modules/meeting/app/forms/meeting/title.rb @@ -47,7 +47,7 @@ class Meeting::Title < ApplicationForm scheme: :secondary, label: I18n.t(:button_cancel), tag: :a, - data: { 'turbo-stream': true }, + data: { "turbo-stream": true }, href: OpenProject::StaticRouting::StaticUrlHelpers.new.cancel_edit_meeting_path(@meeting) ) end diff --git a/modules/meeting/app/models/activities/meeting_activity_provider.rb b/modules/meeting/app/models/activities/meeting_activity_provider.rb index 21a2e800fedf..45f51b1f0ccf 100644 --- a/modules/meeting/app/models/activities/meeting_activity_provider.rb +++ b/modules/meeting/app/models/activities/meeting_activity_provider.rb @@ -27,7 +27,7 @@ #++ class Activities::MeetingActivityProvider < Activities::BaseActivityProvider - activity_provider_for type: 'meetings', + activity_provider_for type: "meetings", activities: %i[meeting meeting_content], permission: :view_meetings @@ -35,7 +35,7 @@ def extend_event_query(query) case activity when :meeting_content query.join(meetings_table).on(activity_journals_table[:meeting_id].eq(meetings_table[:id])) - join_cond = journals_table[:journable_type].eq('MeetingContent') + join_cond = journals_table[:journable_type].eq("MeetingContent") query.join(meeting_contents_table).on(journals_table[:journable_id].eq(meeting_contents_table[:id]).and(join_cond)) else super @@ -46,17 +46,17 @@ def event_query_projection case activity when :meeting [ - activity_journal_projection_statement(:title, 'meeting_title'), - activity_journal_projection_statement(:start_time, 'meeting_start_time'), - activity_journal_projection_statement(:duration, 'meeting_duration'), - activity_journal_projection_statement(:project_id, 'project_id') + activity_journal_projection_statement(:title, "meeting_title"), + activity_journal_projection_statement(:start_time, "meeting_start_time"), + activity_journal_projection_statement(:duration, "meeting_duration"), + activity_journal_projection_statement(:project_id, "project_id") ] else [ - projection_statement(meeting_contents_table, :type, 'meeting_content_type'), - projection_statement(meetings_table, :id, 'meeting_id'), - projection_statement(meetings_table, :title, 'meeting_title'), - projection_statement(meetings_table, :project_id, 'project_id') + projection_statement(meeting_contents_table, :type, "meeting_content_type"), + projection_statement(meetings_table, :id, "meeting_id"), + projection_statement(meetings_table, :title, "meeting_title"), + projection_statement(meetings_table, :project_id, "project_id") ] end end @@ -86,13 +86,13 @@ def activity_journals_table protected def event_name(event) - case event['event_description'] - when 'Agenda closed' - I18n.t('meeting_agenda_closed', scope: 'events') - when 'Agenda opened' - I18n.t('meeting_agenda_opened', scope: 'events') - when 'Minutes created' - I18n.t('meeting_minutes_created', scope: 'events') + case event["event_description"] + when "Agenda closed" + I18n.t("meeting_agenda_closed", scope: "events") + when "Agenda opened" + I18n.t("meeting_agenda_opened", scope: "events") + when "Minutes created" + I18n.t("meeting_minutes_created", scope: "events") else super end @@ -101,12 +101,12 @@ def event_name(event) def event_title(event) case activity when :meeting - start_time = if event['meeting_start_time'].is_a?(String) - DateTime.parse(event['meeting_start_time']) + start_time = if event["meeting_start_time"].is_a?(String) + DateTime.parse(event["meeting_start_time"]) else - event['meeting_start_time'] + event["meeting_start_time"] end - end_time = start_time + event['meeting_duration'].to_f.hours + end_time = start_time + event["meeting_duration"].to_f.hours fstart_with = format_date start_time fstart_without = format_time start_time, false @@ -121,9 +121,9 @@ def event_title(event) def event_type(event) case activity when :meeting - 'meeting' + "meeting" else - event['meeting_content_type'].include?('Agenda') ? 'meeting-agenda' : 'meeting-minutes' + event["meeting_content_type"].include?("Agenda") ? "meeting-agenda" : "meeting-minutes" end end @@ -164,6 +164,6 @@ def meeting_contents_table end def activity_id(event) - activity == :meeting ? event['journable_id'] : event['meeting_id'] + activity == :meeting ? event["journable_id"] : event["meeting_id"] end end diff --git a/modules/meeting/spec/services/meetings/copy_service_integration_spec.rb b/modules/meeting/spec/services/meetings/copy_service_integration_spec.rb index 3b6a3addbadf..c103397bc3e0 100644 --- a/modules/meeting/spec/services/meetings/copy_service_integration_spec.rb +++ b/modules/meeting/spec/services/meetings/copy_service_integration_spec.rb @@ -48,7 +48,7 @@ expect(copy.start_time).to eq(meeting.start_time + 1.week) end - context 'when the meeting is closed' do + context "when the meeting is closed" do it "reopens the meeting" do meeting.update! state: "closed" expect(service_result).to be_success diff --git a/modules/reporting/lib/widget/cost_types.rb b/modules/reporting/lib/widget/cost_types.rb index 67e63d3c7769..9ac7b4aac47c 100644 --- a/modules/reporting/lib/widget/cost_types.rb +++ b/modules/reporting/lib/widget/cost_types.rb @@ -31,7 +31,7 @@ def render_with_options(options, &) @cost_types = options.delete(:cost_types) @selected_type_id = options.delete(:selected_type_id) - super(options, &) + super end def render diff --git a/modules/reporting/lib/widget/reporting_widget.rb b/modules/reporting/lib/widget/reporting_widget.rb index e413e5ffe088..3e198fac1a70 100644 --- a/modules/reporting/lib/widget/reporting_widget.rb +++ b/modules/reporting/lib/widget/reporting_widget.rb @@ -40,7 +40,7 @@ class Widget::ReportingWidget < ActionView::Base attr_accessor :output_buffer, :controller, :config, :_content_for, :_routes, :subject def self.new(subject) - super(subject).tap do |o| + super.tap do |o| o.subject = subject end end diff --git a/modules/storages/spec/features/delete_project_storage_and_file_links_spec.rb b/modules/storages/spec/features/delete_project_storage_and_file_links_spec.rb index ff0e9b2af7ff..21a69db16310 100644 --- a/modules/storages/spec/features/delete_project_storage_and_file_links_spec.rb +++ b/modules/storages/spec/features/delete_project_storage_and_file_links_spec.rb @@ -33,7 +33,7 @@ # Test if the deletion of a ProjectStorage actually deletes related FileLink # objects. -RSpec.describe "Delete ProjectStorage with FileLinks", :js, :with_cuprite, :webmock do +RSpec.describe "Delete ProjectStorage with FileLinks", :js, :webmock, :with_cuprite do let(:user) { create(:user) } let(:role) { create(:project_role, permissions: [:manage_files_in_project]) } let(:project) do @@ -69,7 +69,7 @@ visit external_file_storages_project_settings_project_storages_path(project) # The list of enabled file storages should now contain Storage 1 - expect(page).to have_selector('h1', text: 'Files') + expect(page).to have_css("h1", text: "Files") expect(page).to have_text("Storage 1") # Press Delete icon to remove the storage from the project diff --git a/modules/storages/spec/features/hide_attachments_spec.rb b/modules/storages/spec/features/hide_attachments_spec.rb index 1f1ac0b4d302..9a96d5193974 100644 --- a/modules/storages/spec/features/hide_attachments_spec.rb +++ b/modules/storages/spec/features/hide_attachments_spec.rb @@ -74,7 +74,7 @@ context "if Setting.show_work_package_attachments is false", with_settings: { show_work_package_attachments: false } do let(:project) { create(:project) } - it 'renders the toggle as off for project with not set deactivate_work_package_attachments' do + it "renders the toggle as off for project with not set deactivate_work_package_attachments" do expect(project.deactivate_work_package_attachments).to be_nil login_as current_user @@ -89,7 +89,7 @@ context "if Setting.show_work_package_attachments is true", with_settings: { show_work_package_attachments: true } do let(:project) { create(:project) } - it 'renders the toggle as on for project with not set deactivate_work_package_attachments' do + it "renders the toggle as on for project with not set deactivate_work_package_attachments" do expect(project.deactivate_work_package_attachments).to be_nil login_as current_user diff --git a/modules/storages/spec/features/manage_project_storage_spec.rb b/modules/storages/spec/features/manage_project_storage_spec.rb index 758055dd9f03..df11ab2e0708 100644 --- a/modules/storages/spec/features/manage_project_storage_spec.rb +++ b/modules/storages/spec/features/manage_project_storage_spec.rb @@ -38,10 +38,7 @@ # We decrease the notification polling interval because some portions of the JS code rely on something triggering # the Angular change detection. This is usually done by the notification polling, but we don't want to wait RSpec.describe("Activation of storages in projects", - :js, - :with_cuprite, - :webmock, - with_settings: { notifications_polling_interval: 1_000 }) do + :js, :webmock, :with_cuprite, with_settings: { notifications_polling_interval: 1_000 }) do let(:user) { create(:user) } # The first page is the Project -> Settings -> General page, so we need # to provide the user with the edit_project permission in the role. @@ -112,7 +109,7 @@ expect(page).to have_title("Files") expect(page).to have_current_path external_file_storages_project_settings_project_storages_path(project) expect(page).to have_text(I18n.t("storages.no_results")) - page.first(:link, 'New storage').click + page.first(:link, "New storage").click # Can cancel the creation of a new file storage expect(page).to have_current_path new_project_settings_project_storage_path(project_id: project) @@ -121,7 +118,7 @@ expect(page).to have_current_path external_file_storages_project_settings_project_storages_path(project) # Enable one file storage together with a project folder mode - page.first(:link, 'New storage').click + page.first(:link, "New storage").click expect(page).to have_current_path new_project_settings_project_storage_path(project_id: project) expect(page).to have_text("Add a file storage") expect(page).to have_select("storages_project_storage_storage_id", @@ -149,14 +146,14 @@ page.click_button("Add") # The list of enabled file storages should now contain Storage 1 - expect(page).to have_selector('h1', text: 'Files') + expect(page).to have_css("h1", text: "Files") expect(page).to have_text(storage.name) # Press Edit icon to change the project folder mode to inactive page.find(".icon.icon-edit").click expect(page).to have_current_path edit_project_settings_project_storage_path(project_id: project, id: Storages::ProjectStorage.last, - storages_project_storage: {project_folder_mode: "manual"}) + storages_project_storage: { project_folder_mode: "manual" }) expect(page).to have_text("Edit the file storage to this project") expect(page).to have_no_select("storages_project_storage_storage_id") expect(page).to have_text(storage.name) @@ -169,14 +166,14 @@ page.click_button("Save") # The list of enabled file storages should still contain Storage 1 - expect(page).to have_selector('h1', text: 'Files') + expect(page).to have_css("h1", text: "Files") expect(page).to have_text(storage.name) # Click Edit icon again but cancel the edit page.find(".icon.icon-edit").click expect(page).to have_current_path edit_project_settings_project_storage_path(project_id: project, id: Storages::ProjectStorage.last, - storages_project_storage: {project_folder_mode: "inactive"}) + storages_project_storage: { project_folder_mode: "inactive" }) expect(page).to have_text("Edit the file storage to this project") page.click_link("Cancel") expect(page).to have_current_path external_file_storages_project_settings_project_storages_path(project) @@ -237,7 +234,7 @@ it "excludes storages that are not configured correctly" do visit external_file_storages_project_settings_project_storages_path(project) - page.first(:link, 'New storage').click + page.first(:link, "New storage").click aggregate_failures "select field options" do expect(page).to have_select("storages_project_storage_storage_id", diff --git a/modules/storages/spec/features/storages/project_settings/oauth_access_grant_spec.rb b/modules/storages/spec/features/storages/project_settings/oauth_access_grant_spec.rb index a1af0089e163..55f6c9189529 100644 --- a/modules/storages/spec/features/storages/project_settings/oauth_access_grant_spec.rb +++ b/modules/storages/spec/features/storages/project_settings/oauth_access_grant_spec.rb @@ -75,7 +75,7 @@ expect(page).to have_checked_field("New folder with automatically managed permissions") click_on("Add") - expect(page).to have_selector('h1', text: 'Files') + expect(page).to have_css("h1", text: "Files") expect(page).to have_text(storage.name) within_test_selector("oauth-access-grant-nudge-modal") do diff --git a/spec/components/members/role_form_component_spec.rb b/spec/components/members/role_form_component_spec.rb index b2df3d14abd2..bd2b550d566a 100644 --- a/spec/components/members/role_form_component_spec.rb +++ b/spec/components/members/role_form_component_spec.rb @@ -79,7 +79,7 @@ expect(form).to have_css "input[name='member[user_ids][]']", visible: :hidden # rubocop:disable Capybara/SpecificMatcher - expect(form.first("input[name='member[user_ids][]']", visible: :hidden).value).to eq '42' + expect(form.first("input[name='member[user_ids][]']", visible: :hidden).value).to eq "42" end end end diff --git a/spec/controllers/concerns/authorization_spec.rb b/spec/controllers/concerns/authorization_spec.rb index ac9dbd42f894..63c451dcd6dc 100644 --- a/spec/controllers/concerns/authorization_spec.rb +++ b/spec/controllers/concerns/authorization_spec.rb @@ -28,7 +28,7 @@ require "spec_helper" -RSpec.describe ApplicationController, "enforcement of authorization" do # rubocop:disable RSpec/FilePath, RSpec/SpecFilePathFormat +RSpec.describe ApplicationController, "enforcement of authorization" do # rubocop:disable RSpec/RSpec/SpecFilePathFormat shared_let(:user) { create(:user) } controller_setup = Module.new do diff --git a/spec/features/admin/custom_fields/link_custom_field_spec.rb b/spec/features/admin/custom_fields/link_custom_field_spec.rb index c5b062959468..69377f473916 100644 --- a/spec/features/admin/custom_fields/link_custom_field_spec.rb +++ b/spec/features/admin/custom_fields/link_custom_field_spec.rb @@ -53,7 +53,7 @@ # Expect field to be created cf = CustomField.last expect(cf.name).to eq("My Link CF") - expect(cf.field_format).to eq 'link' + expect(cf.field_format).to eq "link" # Edit again find("a", text: "My Link CF").click diff --git a/spec/features/admin/project_custom_fields/list_spec.rb b/spec/features/admin/project_custom_fields/list_spec.rb index 2c07ed5e272f..612cd42a6735 100644 --- a/spec/features/admin/project_custom_fields/list_spec.rb +++ b/spec/features/admin/project_custom_fields/list_spec.rb @@ -26,29 +26,29 @@ # See COPYRIGHT and LICENSE files for more details. #++ -require 'spec_helper' -require_relative 'shared_context' +require "spec_helper" +require_relative "shared_context" -RSpec.describe 'List project custom fields', :js do - include_context 'with seeded project custom fields' +RSpec.describe "List project custom fields", :js do + include_context "with seeded project custom fields" - context 'with unsufficient permissions' do - it 'is not accessible' do + context "with unsufficient permissions" do + it "is not accessible" do login_as(non_admin) visit admin_settings_project_custom_fields_path - expect(page).to have_text('You are not authorized to access this page.') + expect(page).to have_text("You are not authorized to access this page.") end end - context 'with sufficient permissions' do + context "with sufficient permissions" do before do login_as(admin) visit admin_settings_project_custom_fields_path end - it 'shows all sections in the correct order and allows reordering via menu or drag and drop' do - containers = page.all('.op-project-custom-field-section-container') + it "shows all sections in the correct order and allows reordering via menu or drag and drop" do + containers = page.all(".op-project-custom-field-section-container") expect(containers[0].text).to include(section_for_input_fields.name) expect(containers[1].text).to include(section_for_select_fields.name) @@ -58,7 +58,7 @@ visit admin_settings_project_custom_fields_path - containers = page.all('.op-project-custom-field-section-container') + containers = page.all(".op-project-custom-field-section-container") expect(containers[0].text).to include(section_for_input_fields.name) expect(containers[1].text).to include(section_for_multi_select_fields.name) @@ -67,9 +67,9 @@ # TODO: Add drag and drop test end - it 'allows to delete a section only if no project custom fields are assigned to it' do + it "allows to delete a section only if no project custom fields are assigned to it" do within_project_custom_field_section_menu(section_for_multi_select_fields) do - expect(page).to have_css("button[aria-disabled='true']", text: 'Delete') + expect(page).to have_css("button[aria-disabled='true']", text: "Delete") end multi_list_project_custom_field.destroy @@ -79,11 +79,11 @@ visit admin_settings_project_custom_fields_path within_project_custom_field_section_menu(section_for_multi_select_fields) do - expect(page).to have_no_css("button[aria-disabled='true']", text: 'Delete') - expect(page).to have_button('Delete') + expect(page).to have_no_css("button[aria-disabled='true']", text: "Delete") + expect(page).to have_button("Delete") accept_confirm do - click_on('Delete') + click_on("Delete") end end @@ -91,42 +91,42 @@ .to have_no_css("[data-test-selector='project-custom-field-section-container-#{section_for_multi_select_fields.id}']") end - it 'allows to edit a section' do + it "allows to edit a section" do within_project_custom_field_section_menu(section_for_input_fields) do - click_on('Edit title') + click_on("Edit title") end - fill_in('project_custom_field_section_name', with: 'Updated section name') + fill_in("project_custom_field_section_name", with: "Updated section name") - click_on('Save') + click_on("Save") expect(page).to have_no_text(section_for_input_fields.name) - expect(page).to have_text('Updated section name') + expect(page).to have_text("Updated section name") end - it 'allows to create a new section' do - within '#settings-project-custom-fields-header-component' do - click_on('dialog-show-project-custom-field-section-dialog') + it "allows to create a new section" do + within "#settings-project-custom-fields-header-component" do + click_on("dialog-show-project-custom-field-section-dialog") end - fill_in('project_custom_field_section_name', with: 'New section name') + fill_in("project_custom_field_section_name", with: "New section name") - click_on('Save') + click_on("Save") - expect(page).to have_text('New section name') + expect(page).to have_text("New section name") - containers = page.all('.op-project-custom-field-section-container') + containers = page.all(".op-project-custom-field-section-container") - expect(containers[0].text).to include('New section name') + expect(containers[0].text).to include("New section name") expect(containers[1].text).to include(section_for_input_fields.name) expect(containers[2].text).to include(section_for_select_fields.name) expect(containers[3].text).to include(section_for_multi_select_fields.name) end - describe 'managing project custom fields' do - it 'shows all custom fields in the correct order within their section and allows reordering via menu or drag and drop' do + describe "managing project custom fields" do + it "shows all custom fields in the correct order within their section and allows reordering via menu or drag and drop" do within_project_custom_field_section_container(section_for_input_fields) do - containers = page.all('.op-project-custom-field-container') + containers = page.all(".op-project-custom-field-container") expect(containers[0].text).to include(boolean_project_custom_field.name) expect(containers[1].text).to include(string_project_custom_field.name) @@ -137,7 +137,7 @@ end within_project_custom_field_section_container(section_for_select_fields) do - containers = page.all('.op-project-custom-field-container') + containers = page.all(".op-project-custom-field-container") expect(containers[0].text).to include(list_project_custom_field.name) expect(containers[1].text).to include(version_project_custom_field.name) @@ -145,7 +145,7 @@ end within_project_custom_field_section_container(section_for_multi_select_fields) do - containers = page.all('.op-project-custom-field-container') + containers = page.all(".op-project-custom-field-container") expect(containers[0].text).to include(multi_list_project_custom_field.name) expect(containers[1].text).to include(multi_version_project_custom_field.name) @@ -157,7 +157,7 @@ visit admin_settings_project_custom_fields_path within_project_custom_field_section_container(section_for_multi_select_fields) do - containers = page.all('.op-project-custom-field-container') + containers = page.all(".op-project-custom-field-container") expect(containers[0].text).to include(multi_list_project_custom_field.name) expect(containers[1].text).to include(multi_user_project_custom_field.name) @@ -167,9 +167,9 @@ # TODO: Add drag and drop test end - it 'shows the number of projects using a custom field' do + it "shows the number of projects using a custom field" do within_project_custom_field_container(boolean_project_custom_field) do - expect(page).to have_text('0 Projects') + expect(page).to have_text("0 Projects") end project = create(:project) @@ -178,29 +178,29 @@ visit admin_settings_project_custom_fields_path within_project_custom_field_container(boolean_project_custom_field) do - expect(page).to have_text('1 Project') + expect(page).to have_text("1 Project") end end - it 'allows to delete a custom field' do + it "allows to delete a custom field" do within_project_custom_field_menu(boolean_project_custom_field) do accept_confirm do - click_on('Delete') + click_on("Delete") end end expect(page).to have_no_css("[data-test-selector='project-custom-field-container-#{boolean_project_custom_field.id}']") end - it 'redirects to the custom field edit page via menu item' do + it "redirects to the custom field edit page via menu item" do within_project_custom_field_menu(boolean_project_custom_field) do - click_on('Edit') + click_on("Edit") end expect(page).to have_current_path(edit_admin_settings_project_custom_field_path(boolean_project_custom_field)) end - it 'redirects to the custom field edit page via click on the name of the custom field' do + it "redirects to the custom field edit page via click on the name of the custom field" do within_project_custom_field_container(boolean_project_custom_field) do click_on(boolean_project_custom_field.name) end @@ -208,13 +208,13 @@ expect(page).to have_current_path(edit_admin_settings_project_custom_field_path(boolean_project_custom_field)) end - it 'redirects to the custom field new page via header menu button' do + it "redirects to the custom field new page via header menu button" do page.find("[data-test-selector='new-project-custom-field-button']").click - expect(page).to have_current_path(new_admin_settings_project_custom_field_path(type: 'ProjectCustomField')) + expect(page).to have_current_path(new_admin_settings_project_custom_field_path(type: "ProjectCustomField")) end - it 'redirects to the custom field new page via button in empty sections' do + it "redirects to the custom field new page via button in empty sections" do within_project_custom_field_section_container(section_for_multi_select_fields) do expect(page).to have_no_css("[data-test-selector='new-project-custom-field-button']") end @@ -230,7 +230,7 @@ end expect(page).to have_current_path(new_admin_settings_project_custom_field_path( - type: 'ProjectCustomField', + type: "ProjectCustomField", custom_field_section_id: section_for_multi_select_fields.id )) end @@ -246,7 +246,7 @@ def within_project_custom_field_section_container(section, &block) def within_project_custom_field_section_menu(section, &block) within_project_custom_field_section_container(section) do page.find("[data-test-selector='project-custom-field-section-action-menu']").click - within('anchored-position', &block) + within("anchored-position", &block) end end @@ -264,7 +264,7 @@ def within_project_custom_field_container(custom_field, &block) def within_project_custom_field_menu(section, &block) within_project_custom_field_container(section) do page.find("[data-test-selector='project-custom-field-action-menu']").click - within('anchored-position', &block) + within("anchored-position", &block) end end diff --git a/spec/features/projects/favorite_spec.rb b/spec/features/projects/favorite_spec.rb index bc581a19456c..d3c47dd7f647 100644 --- a/spec/features/projects/favorite_spec.rb +++ b/spec/features/projects/favorite_spec.rb @@ -44,6 +44,7 @@ let(:my_page) do Pages::My::Page.new end + context "as a user" do before do login_as user diff --git a/spec/features/projects/project_custom_fields/overview_page/dialog/permission_spec.rb b/spec/features/projects/project_custom_fields/overview_page/dialog/permission_spec.rb index aec9e99269a7..b8a2d54f196e 100644 --- a/spec/features/projects/project_custom_fields/overview_page/dialog/permission_spec.rb +++ b/spec/features/projects/project_custom_fields/overview_page/dialog/permission_spec.rb @@ -26,15 +26,15 @@ # See COPYRIGHT and LICENSE files for more details. #++ -require 'spec_helper' -require_relative '../shared_context' +require "spec_helper" +require_relative "../shared_context" -RSpec.describe 'Edit project custom fields on project overview page', :js do - include_context 'with seeded projects, members and project custom fields' +RSpec.describe "Edit project custom fields on project overview page", :js do + include_context "with seeded projects, members and project custom fields" let(:overview_page) { Pages::Projects::Show.new(project) } - describe 'with insufficient permissions' do + describe "with insufficient permissions" do # turboframe sidebar request is covered by a controller spec checking for 403 # async dialog content request is be covered by a controller spec checking for 403 # via spec/permissions/manage_project_custom_values_spec.rb @@ -43,20 +43,20 @@ overview_page.visit_page end - it 'does not show the edit buttons' do + it "does not show the edit buttons" do overview_page.within_async_loaded_sidebar do expect(page).to have_no_css("[data-test-selector='project-custom-field-section-edit-button']") end end end - describe 'with sufficient permissions' do + describe "with sufficient permissions" do before do login_as member_with_project_edit_permissions overview_page.visit_page end - it 'shows the edit buttons' do + it "shows the edit buttons" do overview_page.within_async_loaded_sidebar do expect(page).to have_css("[data-test-selector='project-custom-field-section-edit-button']", count: 3) end diff --git a/spec/features/projects/project_custom_fields/settings/mapping_spec.rb b/spec/features/projects/project_custom_fields/settings/mapping_spec.rb index d30b14b7f698..940c4c02bb89 100644 --- a/spec/features/projects/project_custom_fields/settings/mapping_spec.rb +++ b/spec/features/projects/project_custom_fields/settings/mapping_spec.rb @@ -26,16 +26,16 @@ # See COPYRIGHT and LICENSE files for more details. #++ -require 'spec_helper' +require "spec_helper" -RSpec.describe 'Projects custom fields mapping via project settings', :js, :with_cuprite do - let(:project) { create(:project, name: 'Foo project', identifier: 'foo-project') } - let(:other_project) { create(:project, name: 'Bar project', identifier: 'bar-project') } +RSpec.describe "Projects custom fields mapping via project settings", :js, :with_cuprite do + let(:project) { create(:project, name: "Foo project", identifier: "foo-project") } + let(:other_project) { create(:project, name: "Bar project", identifier: "bar-project") } let!(:user_with_sufficient_permissions) do create(:user, - firstname: 'Project', - lastname: 'Admin', + firstname: "Project", + lastname: "Admin", member_with_permissions: { project => %w[ view_work_packages @@ -52,8 +52,8 @@ let!(:member_in_project) do create(:user, - firstname: 'Member 1', - lastname: 'In Project', + firstname: "Member 1", + lastname: "In Project", member_with_permissions: { project => %w[ edit_project view_work_packages @@ -62,69 +62,69 @@ let!(:another_member_in_project) do create(:user, - firstname: 'Member 2', - lastname: 'In Project', + firstname: "Member 2", + lastname: "In Project", member_with_permissions: { project => %w[ view_work_packages ] }) end - let!(:section_for_input_fields) { create(:project_custom_field_section, name: 'Input fields') } - let!(:section_for_select_fields) { create(:project_custom_field_section, name: 'Select fields') } - let!(:section_for_multi_select_fields) { create(:project_custom_field_section, name: 'Multi select fields') } + let!(:section_for_input_fields) { create(:project_custom_field_section, name: "Input fields") } + let!(:section_for_select_fields) { create(:project_custom_field_section, name: "Select fields") } + let!(:section_for_multi_select_fields) { create(:project_custom_field_section, name: "Multi select fields") } let!(:boolean_project_custom_field) do - create(:boolean_project_custom_field, name: 'Boolean field', + create(:boolean_project_custom_field, name: "Boolean field", project_custom_field_section: section_for_input_fields) end let!(:string_project_custom_field) do - create(:string_project_custom_field, name: 'String field', + create(:string_project_custom_field, name: "String field", project_custom_field_section: section_for_input_fields) end let!(:list_project_custom_field) do - create(:list_project_custom_field, name: 'List field', + create(:list_project_custom_field, name: "List field", project_custom_field_section: section_for_select_fields, - possible_values: ['Option 1', 'Option 2', 'Option 3']) + possible_values: ["Option 1", "Option 2", "Option 3"]) end let!(:multi_list_project_custom_field) do - create(:list_project_custom_field, name: 'Multi list field', + create(:list_project_custom_field, name: "Multi list field", project_custom_field_section: section_for_multi_select_fields, - possible_values: ['Option 1', 'Option 2', 'Option 3'], + possible_values: ["Option 1", "Option 2", "Option 3"], multi_value: true) end - describe 'with insufficient permissions' do + describe "with insufficient permissions" do before do login_as member_in_project # can edit project but is not allowed to select project custom fields end - it 'does not show the menu entry in the project settings menu' do + it "does not show the menu entry in the project settings menu" do visit project_settings_general_path(project) - within '#menu-sidebar' do + within "#menu-sidebar" do expect(page).to have_no_css("li[data-name='settings_project_custom_fields']") end end - it 'does not show the project custom fields page' do + it "does not show the project custom fields page" do visit project_settings_project_custom_fields_path(project) - expect(page).to have_content('You are not authorized to access this page.') + expect(page).to have_content("You are not authorized to access this page.") end end - describe 'with sufficient permissions' do + describe "with sufficient permissions" do before do login_as user_with_sufficient_permissions end - it 'does show the menu entry in the project settings menu' do + it "does show the menu entry in the project settings menu" do visit project_settings_general_path(project) - within '#menu-sidebar' do + within "#menu-sidebar" do expect(page).to have_css("li[data-name='settings_project_custom_fields']") end end @@ -151,17 +151,17 @@ expect(page).to have_content("Multi list field") end - it 'shows all available project custom fields with their correct mapping state' do + it "shows all available project custom fields with their correct mapping state" do visit project_settings_project_custom_fields_path(project) within_custom_field_section_container(section_for_input_fields) do within_custom_field_container(boolean_project_custom_field) do - expect(page).to have_content('Boolean field') + expect(page).to have_content("Boolean field") expect_type("Bool") expect_unchecked_state end within_custom_field_container(string_project_custom_field) do - expect(page).to have_content('String field') + expect(page).to have_content("String field") expect_type("String") expect_unchecked_state end @@ -169,7 +169,7 @@ within_custom_field_section_container(section_for_select_fields) do within_custom_field_container(list_project_custom_field) do - expect(page).to have_content('List field') + expect(page).to have_content("List field") expect_type("List") expect_unchecked_state end @@ -177,14 +177,14 @@ within_custom_field_section_container(section_for_multi_select_fields) do within_custom_field_container(multi_list_project_custom_field) do - expect(page).to have_content('Multi list field') + expect(page).to have_content("Multi list field") expect_type("List") expect_unchecked_state end end end - it 'toggles the mapping state of a project custom field for a specific project when clicked' do + it "toggles the mapping state of a project custom field for a specific project when clicked" do visit project_settings_project_custom_fields_path(project) within_custom_field_section_container(section_for_input_fields) do @@ -214,7 +214,7 @@ end end - it 'enables all mapping states of a section for a specific project when bulk action button clicked' do + it "enables all mapping states of a section for a specific project when bulk action button clicked" do visit project_settings_project_custom_fields_path(project) within_custom_field_section_container(section_for_input_fields) do @@ -241,7 +241,7 @@ end end - it 'disables all mapping states of a section for a specific project when bulk action button clicked' do + it "disables all mapping states of a section for a specific project when bulk action button clicked" do visit project_settings_project_custom_fields_path(project) within_custom_field_section_container(section_for_input_fields) do @@ -279,59 +279,59 @@ end end - it 'filters the project custom fields by name with given user input' do + it "filters the project custom fields by name with given user input" do visit project_settings_project_custom_fields_path(project) - fill_in 'project-custom-fields-mapping-filter', with: 'Boolean' + fill_in "project-custom-fields-mapping-filter", with: "Boolean" within_custom_field_section_container(section_for_input_fields) do - expect(page).to have_content('Boolean field') - expect(page).to have_no_content('String field') + expect(page).to have_content("Boolean field") + expect(page).to have_no_content("String field") end within_custom_field_section_container(section_for_select_fields) do - expect(page).to have_no_content('List field') + expect(page).to have_no_content("List field") end within_custom_field_section_container(section_for_multi_select_fields) do - expect(page).to have_no_content('Multi list field') + expect(page).to have_no_content("Multi list field") end end - it 'shows the project custom field sections in the correct order' do + it "shows the project custom field sections in the correct order" do visit project_settings_project_custom_fields_path(project) - sections = page.all('.op-project-custom-field-section') + sections = page.all(".op-project-custom-field-section") expect(sections.size).to eq(3) - expect(sections[0].text).to include('Input fields') - expect(sections[1].text).to include('Select fields') - expect(sections[2].text).to include('Multi select fields') + expect(sections[0].text).to include("Input fields") + expect(sections[1].text).to include("Select fields") + expect(sections[2].text).to include("Multi select fields") section_for_input_fields.move_to_bottom visit project_settings_project_custom_fields_path(project) - sections = page.all('.op-project-custom-field-section') + sections = page.all(".op-project-custom-field-section") expect(sections.size).to eq(3) - expect(sections[0].text).to include('Select fields') - expect(sections[1].text).to include('Multi select fields') - expect(sections[2].text).to include('Input fields') + expect(sections[0].text).to include("Select fields") + expect(sections[1].text).to include("Multi select fields") + expect(sections[2].text).to include("Input fields") end - it 'shows the project custom fields in the correct order within the sections' do + it "shows the project custom fields in the correct order within the sections" do visit project_settings_project_custom_fields_path(project) within_custom_field_section_container(section_for_input_fields) do - custom_fields = page.all('.op-project-custom-field') + custom_fields = page.all(".op-project-custom-field") expect(custom_fields.size).to eq(2) - expect(custom_fields[0].text).to include('Boolean field') - expect(custom_fields[1].text).to include('String field') + expect(custom_fields[0].text).to include("Boolean field") + expect(custom_fields[1].text).to include("String field") end boolean_project_custom_field.move_to_bottom @@ -339,21 +339,21 @@ visit project_settings_project_custom_fields_path(project) within_custom_field_section_container(section_for_input_fields) do - custom_fields = page.all('.op-project-custom-field') + custom_fields = page.all(".op-project-custom-field") expect(custom_fields.size).to eq(2) - expect(custom_fields[0].text).to include('String field') - expect(custom_fields[1].text).to include('Boolean field') + expect(custom_fields[0].text).to include("String field") + expect(custom_fields[1].text).to include("Boolean field") end end - context 'with visibility of project custom fields' do - let!(:section_with_invisible_fields) { create(:project_custom_field_section, name: 'Section with invisible fields') } + context "with visibility of project custom fields" do + let!(:section_with_invisible_fields) { create(:project_custom_field_section, name: "Section with invisible fields") } let!(:visible_project_custom_field) do create(:project_custom_field, - name: 'Normal field', + name: "Normal field", visible: true, projects: [project], project_custom_field_section: section_with_invisible_fields) @@ -361,13 +361,13 @@ let!(:invisible_project_custom_field) do create(:project_custom_field, - name: 'Admin only field', + name: "Admin only field", visible: false, projects: [project], project_custom_field_section: section_with_invisible_fields) end - context 'with admin permissions' do + context "with admin permissions" do let!(:admin) do create(:admin) end @@ -377,14 +377,14 @@ visit project_settings_project_custom_fields_path(project) end - it 'shows the invisible project custom fields' do + it "shows the invisible project custom fields" do within_custom_field_section_container(section_with_invisible_fields) do - expect(page).to have_content('Normal field') - expect(page).to have_content('Admin only field') + expect(page).to have_content("Normal field") + expect(page).to have_content("Admin only field") end end - it 'includeds the invisible project custom fields in the bulk actions' do + it "includeds the invisible project custom fields in the bulk actions" do within_custom_field_section_container(section_with_invisible_fields) do page .find("[data-test-selector='disable-all-project-custom-field-mappings-#{section_with_invisible_fields.id}']") @@ -411,20 +411,20 @@ end end - context 'with non-admin permissions' do + context "with non-admin permissions" do before do login_as user_with_sufficient_permissions visit project_settings_project_custom_fields_path(project) end - it 'does not show the invisible project custom fields' do + it "does not show the invisible project custom fields" do within_custom_field_section_container(section_with_invisible_fields) do - expect(page).to have_content('Normal field') - expect(page).to have_no_content('Admin only field') + expect(page).to have_content("Normal field") + expect(page).to have_no_content("Admin only field") end end - it 'does not include the invisible project custom fields in the bulk actions' do + it "does not include the invisible project custom fields in the bulk actions" do within_custom_field_section_container(section_with_invisible_fields) do page .find("[data-test-selector='disable-all-project-custom-field-mappings-#{section_with_invisible_fields.id}']") @@ -461,11 +461,11 @@ def expect_type(type) end def expect_checked_state - expect(page).to have_css('.ToggleSwitch-statusOn') + expect(page).to have_css(".ToggleSwitch-statusOn") end def expect_unchecked_state - expect(page).to have_css('.ToggleSwitch-statusOff') + expect(page).to have_css(".ToggleSwitch-statusOff") end def within_custom_field_section_container(section, &) diff --git a/spec/features/work_packages/export_spec.rb b/spec/features/work_packages/export_spec.rb index 74a44afc57f2..a12ca3b80793 100644 --- a/spec/features/work_packages/export_spec.rb +++ b/spec/features/work_packages/export_spec.rb @@ -234,15 +234,16 @@ def export!(expect_success = true) allow_any_instance_of(WorkPackage::PDFExport::WorkPackageListToPdf) .to receive(:export!) .and_return( - ::Exports::Result.new format: :pdf, - title: 'foo', - content: Tempfile.new("something"), - mime_type: "application/pdf" + Exports::Result.new(format: :pdf, + title: "foo", + content: Tempfile.new("something"), + mime_type: "application/pdf") ) - end + end context "table" do let(:export_type) { I18n.t("export.format.pdf_overview_table") } + context "with many columns" do before do # Despite attempts to provoke the error by having a lot of columns, the pdf @@ -292,7 +293,7 @@ def export!(expect_success = true) wp_table.visit_query query work_packages_page.ensure_loaded settings_menu.open_and_choose "Export" - expect(page).not_to have_content(export_type) + expect(page).to have_no_content(export_type) end end @@ -303,7 +304,7 @@ def export!(expect_success = true) it "has no gantt export" do wp_table.visit_query query_tl settings_menu.open_and_choose "Export" - expect(page).not_to have_content(export_type) + expect(page).to have_no_content(export_type) end end diff --git a/spec/features/wysiwyg/macros/attribute_macros_spec.rb b/spec/features/wysiwyg/macros/attribute_macros_spec.rb index 088ae194132a..a1d8a7c6c9b3 100644 --- a/spec/features/wysiwyg/macros/attribute_macros_spec.rb +++ b/spec/features/wysiwyg/macros/attribute_macros_spec.rb @@ -31,34 +31,7 @@ RSpec.describe "Wysiwyg attribute macros", :js do shared_let(:admin) { create(:admin) } let(:user) { admin } - - shared_let(:type_milestone) { create(:type_milestone) } - shared_let(:type_task) { create(:type_task) } - - shared_let(:project) do - create(:project, - identifier: "some-project", - types: [type_milestone, type_task], - enabled_module_names: %w[wiki work_package_tracking]) - end - shared_let(:work_package) do - create(:work_package, - subject: "Foo Bar", - project:, - start_date: '2023-01-01', - due_date: '2023-01-05', - type: type_task) - end - shared_let(:milestone) do - create(:work_package, - subject: "Milestone", - project:, - due_date: '2023-01-10', - type: type_milestone) - end - let(:editor) { Components::WysiwygEditor.new } - let(:markdown) do <<~MD # My headline @@ -100,6 +73,31 @@ MD end + shared_let(:type_milestone) { create(:type_milestone) } + shared_let(:type_task) { create(:type_task) } + + shared_let(:project) do + create(:project, + identifier: "some-project", + types: [type_milestone, type_task], + enabled_module_names: %w[wiki work_package_tracking]) + end + shared_let(:work_package) do + create(:work_package, + subject: "Foo Bar", + project:, + start_date: "2023-01-01", + due_date: "2023-01-05", + type: type_task) + end + shared_let(:milestone) do + create(:work_package, + subject: "Milestone", + project:, + due_date: "2023-01-10", + type: type_milestone) + end + before do login_as(user) end diff --git a/spec/httpx_spec.rb b/spec/httpx_spec.rb index 82208747e9ee..7bb608bb09ff 100644 --- a/spec/httpx_spec.rb +++ b/spec/httpx_spec.rb @@ -1,16 +1,16 @@ -require 'webrick' -require 'httpx' +require "webrick" +require "httpx" -RSpec.describe 'HTTPX' do - describe 'persistent connections' do - it 'does not hang forever when used to request HTTP 1.1 server' do - server = WEBrick::HTTPServer.new(:Port => 8543) - server.mount_proc '/' do |req, res| - res.body = 'Response Body' +RSpec.describe "HTTPX" do + describe "persistent connections" do + it "does not hang forever when used to request HTTP 1.1 server" do + server = WEBrick::HTTPServer.new(Port: 8543) + server.mount_proc "/" do |_req, res| + res.body = "Response Body" end Thread.new { server.start } - session = HTTPX .plugin(:persistent).with(timeout: {keep_alive_timeout: 2}) + session = HTTPX.plugin(:persistent).with(timeout: { keep_alive_timeout: 2 }) number_of_requests_made = 0 begin Timeout.timeout(10) do diff --git a/spec/i18n_spec.rb b/spec/i18n_spec.rb index 540315efb2c3..b921ccc1ec6d 100644 --- a/spec/i18n_spec.rb +++ b/spec/i18n_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'i18n/tasks' +require "i18n/tasks" RSpec.describe I18n do let(:i18n) { I18n::Tasks::BaseTask.new } @@ -8,19 +8,19 @@ let(:unused_keys) { i18n.unused_keys } let(:inconsistent_interpolations) { i18n.inconsistent_interpolations } - it 'does not have missing keys' do - pending 'Enable when i18n-tasks is enabled across the project, otherwise this spec will report false positives' + it "does not have missing keys" do + pending "Enable when i18n-tasks is enabled across the project, otherwise this spec will report false positives" expect(missing_keys).to be_empty, "Missing #{missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them" end - it 'does not have unused keys' do + it "does not have unused keys" do expect(unused_keys).to be_empty, "#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them" end - it 'files are normalized' do + it "files are normalized" do non_normalized = i18n.non_normalized_paths error_message = "The following files need to be normalized:\n" \ "#{non_normalized.map { |path| " #{path}" }.join("\n")}\n" \ @@ -28,12 +28,12 @@ expect(non_normalized).to be_empty, error_message end - context 'for all i18n files' do - let(:root_dir) { Pathname.new(__FILE__).dirname.join('..') } - let(:config_file) { root_dir.join('config/i18n-tasks-all-files.yml') } + context "for all i18n files" do + let(:root_dir) { Pathname.new(__FILE__).dirname.join("..") } + let(:config_file) { root_dir.join("config/i18n-tasks-all-files.yml") } let(:i18n) { I18n::Tasks::BaseTask.new(config_file:) } - it 'does not have inconsistent interpolations' do + it "does not have inconsistent interpolations" do config_file_relative_path = config_file.relative_path_from(Dir.pwd) error_message = "#{inconsistent_interpolations.leaves.count} i18n keys have inconsistent interpolations.\n" \ "Run 'i18n-tasks check-consistent-interpolations --config #{config_file_relative_path}' to show them" diff --git a/spec/models/queries/projects/project_queries/scopes/allowed_to_spec.rb b/spec/models/queries/projects/project_queries/scopes/allowed_to_spec.rb index bb6eb80ab6e8..add53403ed2a 100644 --- a/spec/models/queries/projects/project_queries/scopes/allowed_to_spec.rb +++ b/spec/models/queries/projects/project_queries/scopes/allowed_to_spec.rb @@ -28,7 +28,7 @@ require "spec_helper" -RSpec.describe Queries::Projects::ProjectQuery, "#allowed to" do # rubocop:disable RSpec/FilePath,RSpec/SpecFilePathFormat +RSpec.describe Queries::Projects::ProjectQuery, "#allowed to" do # rubocop:disable RSpec/RSpec/SpecFilePathFormat shared_let(:user) { create(:user) } shared_let(:other_user) { create(:user) } diff --git a/spec/models/work_package/work_package_acts_as_journalized_spec.rb b/spec/models/work_package/work_package_acts_as_journalized_spec.rb index 58d2229e2184..baf63383e108 100644 --- a/spec/models/work_package/work_package_acts_as_journalized_spec.rb +++ b/spec/models/work_package/work_package_acts_as_journalized_spec.rb @@ -26,10 +26,10 @@ # See COPYRIGHT and LICENSE files for more details. #++ -require 'spec_helper' +require "spec_helper" RSpec.describe WorkPackage do - describe '#journal' do + describe "#journal" do let(:type) { create(:type) } let(:project) do create(:project, @@ -42,7 +42,7 @@ create(:work_package, project_id: project.id, type:, - description: 'Description', + description: "Description", priority:, status:, duration: 1) @@ -52,53 +52,53 @@ current_user { create(:user) } - context 'for work package creation' do + context "for work package creation" do it { expect(Journal.for_work_package.count).to eq(1) } - it 'has a journal entry' do + it "has a journal entry" do expect(Journal.for_work_package.first.journable).to eq(work_package) end - it 'notes the changes to subject' do + it "notes the changes to subject" do expect(work_package.last_journal.details[:subject]) .to contain_exactly(nil, work_package.subject) end - it 'notes the changes to project' do + it "notes the changes to project" do expect(work_package.last_journal.details[:project_id]) .to contain_exactly(nil, work_package.project_id) end - it 'notes the description' do + it "notes the description" do expect(work_package.last_journal.details[:description]) .to contain_exactly(nil, work_package.description) end - it 'notes the scheduling mode' do + it "notes the scheduling mode" do expect(work_package.last_journal.details[:schedule_manually]) .to contain_exactly(nil, false) end - it 'has the timestamp of the work package update time for created_at' do + it "has the timestamp of the work package update time for created_at" do expect(work_package.last_journal.created_at) .to eql(work_package.reload.updated_at) end - it 'has the updated_at of the work package as the lower bound for validity_period and no upper bound' do + it "has the updated_at of the work package as the lower bound for validity_period and no upper bound" do expect(work_package.last_journal.validity_period) .to eql(work_package.reload.updated_at...) end end - context 'when nothing is changed' do + context "when nothing is changed" do it { expect { work_package.save! }.not_to change(Journal, :count) } - it 'does not update the updated_at time of the work package' do + it "does not update the updated_at time of the work package" do expect { work_package.save! }.not_to change(work_package, :updated_at) end end - context 'for different newlines', with_settings: { journal_aggregation_time_minutes: 0 } do + context "for different newlines", with_settings: { journal_aggregation_time_minutes: 0 } do let(:description) { "Description\n\nwith newlines\n\nembedded" } let(:changed_description) { description.gsub("\n", "\r\n") } let!(:work_package1) do @@ -113,19 +113,19 @@ work_package1.description = changed_description end - context 'when a new journal is created tracking a simultaneously applied change' do + context "when a new journal is created tracking a simultaneously applied change" do before do - work_package1.subject += 'changed' + work_package1.subject += "changed" work_package1.save! end - describe 'does not track the changed newline characters' do + describe "does not track the changed newline characters" do subject { work_package1.last_journal.data.description } it { is_expected.to eq(description) } end - describe 'tracks only the other change' do + describe "tracks only the other change" do subject { work_package1.last_journal.details } it { is_expected.to have_key :subject } @@ -133,7 +133,7 @@ end end - context 'when there is a legacy journal containing non-escaped newlines' do + context "when there is a legacy journal containing non-escaped newlines" do let!(:work_package1) do create(:work_package, journals: { @@ -142,13 +142,13 @@ }) end - it 'does not track the change to the newline characters' do + it "does not track the change to the newline characters" do expect(work_package1.reload.last_journal.details).not_to have_key :description end end end - describe 'on work package change without aggregation', with_settings: { journal_aggregation_time_minutes: 0 } do + describe "on work package change without aggregation", with_settings: { journal_aggregation_time_minutes: 0 } do let(:parent_work_package) do create(:work_package, project_id: project.id, @@ -162,8 +162,8 @@ before do project.types << type2 - work_package.subject = 'changed' - work_package.description = 'changed' + work_package.subject = "changed" + work_package.description = "changed" work_package.type = type2 work_package.status = status2 work_package.priority = priority2 @@ -179,10 +179,10 @@ work_package.save! end - context 'for last created journal' do + context "for last created journal" do subject { work_package.last_journal.details } - it 'contains all changes' do + it "contains all changes" do %i(subject description type_id status_id priority_id start_date due_date estimated_hours assigned_to_id responsible_id parent_id schedule_manually duration).each do |a| @@ -191,106 +191,106 @@ end end - shared_examples_for 'old value' do + shared_examples_for "old value" do subject { work_package.last_journal.old_value_for(property) } it { is_expected.to eq(expected_value) } end - shared_examples_for 'new value' do + shared_examples_for "new value" do subject { work_package.last_journal.new_value_for(property) } it { is_expected.to eq(expected_value) } end - describe 'journaled value for' do - describe 'description' do - let(:property) { 'description' } + describe "journaled value for" do + describe "description" do + let(:property) { "description" } - context 'for old value' do - let(:expected_value) { 'Description' } + context "for old value" do + let(:expected_value) { "Description" } - it_behaves_like 'old value' + it_behaves_like "old value" end - context 'for new value' do - let(:expected_value) { 'changed' } + context "for new value" do + let(:expected_value) { "changed" } - it_behaves_like 'new value' + it_behaves_like "new value" end end - describe 'schedule_manually' do - let(:property) { 'schedule_manually' } + describe "schedule_manually" do + let(:property) { "schedule_manually" } - context 'for old value' do + context "for old value" do let(:expected_value) { false } - it_behaves_like 'old value' + it_behaves_like "old value" end - context 'for new value' do + context "for new value" do let(:expected_value) { true } - it_behaves_like 'new value' + it_behaves_like "new value" end end - describe 'duration' do - let(:property) { 'duration' } + describe "duration" do + let(:property) { "duration" } - context 'for old value' do + context "for old value" do let(:expected_value) { 1 } - it_behaves_like 'old value' + it_behaves_like "old value" end - context 'for new value' do + context "for new value" do let(:expected_value) { 8 } - it_behaves_like 'new value' + it_behaves_like "new value" end end end - describe 'adding journal with a missing journal and an existing journal' do + describe "adding journal with a missing journal and an existing journal" do before do allow(WorkPackages::UpdateContract).to receive(:new).and_return(NoopContract.new) service = WorkPackages::UpdateService.new(user: current_user, model: work_package) - service.call(journal_notes: 'note to be deleted', send_notifications: false) + service.call(journal_notes: "note to be deleted", send_notifications: false) work_package.reload - service.call(description: 'description v2', send_notifications: false) + service.call(description: "description v2", send_notifications: false) work_package.reload - work_package.journals.reload.find_by(notes: 'note to be deleted').delete + work_package.journals.reload.find_by(notes: "note to be deleted").delete - service.call(description: 'description v4', send_notifications: false) + service.call(description: "description v4", send_notifications: false) end - it 'creates a journal for the last change' do + it "creates a journal for the last change" do last_journal = work_package.last_journal - expect(last_journal.data.description).to eql('description v4') + expect(last_journal.data.description).to eql("description v4") end end - it 'has the timestamp of the work package update time for created_at' do + it "has the timestamp of the work package update time for created_at" do expect(work_package.last_journal.created_at) .to eql(work_package.reload.updated_at) end - it 'has the updated_at of the work package as the lower bound for validity_period and no upper bound' do + it "has the updated_at of the work package as the lower bound for validity_period and no upper bound" do expect(work_package.last_journal.validity_period) .to eql(work_package.reload.updated_at...) end - it 'sets the upper bound of the preceeding journal to be the created_at time of the newly created journal' do + it "sets the upper bound of the preceeding journal to be the created_at time of the newly created journal" do former_last_journal = work_package.journals[-2] expect(former_last_journal.validity_period) .to eql(former_last_journal.created_at...work_package.last_journal.created_at) end end - describe 'attachments', with_settings: { journal_aggregation_time_minutes: 0 } do + describe "attachments", with_settings: { journal_aggregation_time_minutes: 0 } do let(:attachment) { build(:attachment) } let(:attachment_id) { "attachments_#{attachment.id}" } @@ -299,7 +299,7 @@ work_package.save! end - context 'for new attachment' do + context "for new attachment" do subject { work_package.last_journal.details } it { is_expected.to have_key attachment_id } @@ -307,22 +307,22 @@ it { expect(subject[attachment_id]).to eq([nil, attachment.filename]) } end - context 'when attachment saved w/o change' do + context "when attachment saved w/o change" do it { expect { attachment.save! }.not_to change(Journal, :count) } end end - describe 'custom values', with_settings: { journal_aggregation_time_minutes: 0 } do + describe "custom values", with_settings: { journal_aggregation_time_minutes: 0 } do let(:custom_field) { create(:work_package_custom_field) } let(:custom_value) do build(:custom_value, - value: 'false', + value: "false", custom_field:) end let(:custom_field_id) { "custom_fields_#{custom_value.custom_field_id}" } - shared_context 'for work package with custom value' do + shared_context "for work package with custom value" do before do project.work_package_custom_fields << custom_field type.custom_fields << custom_field @@ -332,8 +332,8 @@ end end - context 'for new custom value' do - include_context 'for work package with custom value' + context "for new custom value" do + include_context "for work package with custom value" subject { work_package.last_journal.details } @@ -342,12 +342,12 @@ it { expect(subject[custom_field_id]).to eq([nil, custom_value.value]) } end - context 'for custom value modified' do - include_context 'for work package with custom value' + context "for custom value modified" do + include_context "for work package with custom value" let(:modified_custom_value) do create(:work_package_custom_value, - value: 'true', + value: "true", custom_field:) end @@ -363,12 +363,12 @@ it { expect(subject[custom_field_id]).to eq([custom_value.value.to_s, modified_custom_value.value.to_s]) } end - context 'when work package saved w/o change' do - include_context 'for work package with custom value' + context "when work package saved w/o change" do + include_context "for work package with custom value" let(:unmodified_custom_value) do create(:work_package_custom_value, - value: 'false', + value: "false", custom_field:) end @@ -378,15 +378,15 @@ it { expect { work_package.save! }.not_to change(Journal, :count) } - it 'does not set an upper bound to the already existing journal' do + it "does not set an upper bound to the already existing journal" do work_package.save expect(work_package.last_journal.validity_period.end) .to be_nil end end - context 'when custom value removed' do - include_context 'for work package with custom value' + context "when custom value removed" do + include_context "for work package with custom value" before do work_package.custom_values.delete(custom_value) @@ -400,35 +400,35 @@ it { expect(subject[custom_field_id]).to eq([custom_value.value, nil]) } end - context 'when custom value did not exist before' do + context "when custom value did not exist before" do let(:custom_field) do create(:work_package_custom_field, is_required: false, - field_format: 'list', - possible_values: ['', '1', '2', '3', '4', '5', '6', '7']) + field_format: "list", + possible_values: ["", "1", "2", "3", "4", "5", "6", "7"]) end let(:custom_value) do create(:custom_value, - value: '', + value: "", customized: work_package, custom_field:) end - describe 'empty values are recognized as unchanged' do - include_context 'for work package with custom value' + describe "empty values are recognized as unchanged" do + include_context "for work package with custom value" it { expect(work_package.last_journal.customizable_journals).to be_empty } end - describe 'empty values handled as non existing' do - include_context 'for work package with custom value' + describe "empty values handled as non existing" do + include_context "for work package with custom value" it { expect(work_package.last_journal.customizable_journals.count).to eq(0) } end end end - describe 'file_links', with_settings: { journal_aggregation_time_minutes: 0 } do + describe "file_links", with_settings: { journal_aggregation_time_minutes: 0 } do let(:file_link) { build(:file_link) } let(:file_link_id) { "file_links_#{file_link.id}" } @@ -437,18 +437,18 @@ work_package.save! end - context 'for the new file link' do + context "for the new file link" do subject(:journal_details) { work_package.last_journal.details } it { is_expected.to have_key file_link_id } it { expect(journal_details[file_link_id]) - .to eq([nil, { 'link_name' => file_link.origin_name, 'storage_name' => nil }]) + .to eq([nil, { "link_name" => file_link.origin_name, "storage_name" => nil }]) } end - context 'when file link saved w/o change' do + context "when file link saved w/o change" do it { expect do file_link.save @@ -458,56 +458,56 @@ end end - context 'for only journal notes adding' do + context "for only journal notes adding" do subject do - work_package.add_journal(user: User.current, notes: 'some notes') + work_package.add_journal(user: User.current, notes: "some notes") work_package.save work_package end - it 'does not create a new journal entry' do + it "does not create a new journal entry" do expect { subject }.not_to change(work_package, :last_journal) end - it 'has the timestamp of the work package update time for updated_at' do + it "has the timestamp of the work package update time for updated_at" do expect(subject.last_journal.updated_at).to eql(work_package.reload.updated_at) end - it 'updates the updated_at time of the work package' do + it "updates the updated_at time of the work package" do expect { subject.reload }.to change(work_package, :updated_at) end - it 'stores the note with the existing journal entry' do - expect { subject }.to change { work_package.last_journal.notes }.from('').to('some notes') + it "stores the note with the existing journal entry" do + expect { subject }.to change { work_package.last_journal.notes }.from("").to("some notes") end end - context 'for mixed journal notes and attribute adding' do + context "for mixed journal notes and attribute adding" do subject do - work_package.add_journal(user: User.current, notes: 'some notes') - work_package.subject = 'blubs' + work_package.add_journal(user: User.current, notes: "some notes") + work_package.subject = "blubs" work_package.save work_package end - it 'does not create a new journal entry' do + it "does not create a new journal entry" do expect { subject }.not_to change(work_package, :last_journal) end - it 'has the timestamp of the work package update time for updated_at' do + it "has the timestamp of the work package update time for updated_at" do expect(subject.last_journal.updated_at).to eql(work_package.reload.updated_at) end - it 'updates the updated_at time of the work package' do + it "updates the updated_at time of the work package" do expect { subject.reload }.to change(work_package, :updated_at) end - it 'stores the note with the existing journal entry' do - expect { subject }.to change { work_package.last_journal.notes }.from('').to('some notes') + it "stores the note with the existing journal entry" do + expect { subject }.to change { work_package.last_journal.notes }.from("").to("some notes") end end - context 'for only journal cause adding' do + context "for only journal cause adding" do subject do work_package.add_journal( user: User.current, @@ -517,62 +517,62 @@ work_package end - it 'has the cause logged in the last journal' do + it "has the cause logged in the last journal" do expect(subject.last_journal.cause).to eql({ - 'type' => 'work_package_predecessor_changed_times', - 'work_package_id' => other_work_package.id + "type" => "work_package_predecessor_changed_times", + "work_package_id" => other_work_package.id }) end - it 'has the timestamp of the work package update time for created_at' do + it "has the timestamp of the work package update time for created_at" do expect(subject.last_journal.updated_at).to eql(work_package.reload.updated_at) end - it 'updates the updated_at time of the work package' do + it "updates the updated_at time of the work package" do expect { subject.reload }.to change(work_package, :updated_at) end - it 'does create a new journal entry' do + it "does create a new journal entry" do expect { subject }.to change(work_package, :last_journal) end end - context 'for mixed journal cause, notes and attribute adding' do + context "for mixed journal cause, notes and attribute adding" do subject do work_package.add_journal( user: User.current, - notes: 'some notes', + notes: "some notes", cause: Journal::CausedByWorkPackagePredecessorChange.new(other_work_package) ) - work_package.subject = 'blubs' + work_package.subject = "blubs" work_package.save work_package end - it 'has the timestamp of the work package update time for created_at' do + it "has the timestamp of the work package update time for created_at" do expect(work_package.last_journal.updated_at).to eql(work_package.reload.updated_at) end - it 'does create a new journal entry' do + it "does create a new journal entry" do expect { subject }.to change(work_package, :last_journal) end - it 'updates the updated_at time of the work package' do + it "updates the updated_at time of the work package" do updated_at_before = work_package.updated_at expect(subject.reload.updated_at).not_to eql(updated_at_before) end - it 'stores the cause and note with the existing journal entry' do + it "stores the cause and note with the existing journal entry" do subject - expect(work_package.last_journal.notes).to eq('some notes') - expect(work_package.last_journal.cause_type).to eq('work_package_predecessor_changed_times') + expect(work_package.last_journal.notes).to eq("some notes") + expect(work_package.last_journal.cause_type).to eq("work_package_predecessor_changed_times") expect(work_package.last_journal.cause_work_package_id).to eq(other_work_package.id) end end - context 'when 2 updates with the same cause occur' do + context "when 2 updates with the same cause occur" do before do work_package.add_journal( user: User.current, @@ -591,20 +591,20 @@ work_package.save end - it 'does not create a new journal entry' do + it "does not create a new journal entry" do expect { subject }.not_to change(work_package, :last_journal) end - it 'stores the last update only' do + it "stores the last update only" do subject - expect(work_package.last_journal.new_value_for(:subject)).to eq('new subject 2') - expect(work_package.last_journal.cause_type).to eq('work_package_predecessor_changed_times') + expect(work_package.last_journal.new_value_for(:subject)).to eq("new subject 2") + expect(work_package.last_journal.cause_type).to eq("work_package_predecessor_changed_times") expect(work_package.last_journal.cause_work_package_id).to eq(other_work_package.id) end end - context 'when updated within aggregation time' do + context "when updated within aggregation time" do subject(:journals) { work_package.journals } current_user { user1 } @@ -627,18 +627,18 @@ work_package.save! end - context 'as author of last change' do + context "as author of last change" do let(:new_author) { user1 } - it 'leads to a single journal' do + it "leads to a single journal" do expect(subject.count).to be 1 end - it 'is the initial journal' do + it "is the initial journal" do expect(subject.first).to be_initial end - it 'contains the changes of both updates with the later overwriting the former' do + it "contains the changes of both updates with the later overwriting the former" do expect(subject.first.data.status_id) .to eql changes[:status].id @@ -646,51 +646,51 @@ .to eql work_package.type_id end - context 'with a comment' do - let(:notes) { 'This is why I changed it.' } + context "with a comment" do + let(:notes) { "This is why I changed it." } - it 'leads to a single journal with the comment' do + it "leads to a single journal with the comment" do expect(subject.count).to be 1 expect(subject.first.notes) .to eql notes end - context 'when adding a second comment' do - let(:second_notes) { 'Another comment, unrelated to the first one.' } + context "when adding a second comment" do + let(:second_notes) { "Another comment, unrelated to the first one." } before do work_package.add_journal(user: new_author, notes: second_notes) work_package.save! end - it 'returns two journals' do + it "returns two journals" do expect(subject.count).to be 2 expect(subject.first.notes).to eql notes expect(subject.second.notes).to eql second_notes end - it 'has one initial journal and one non-initial journal' do + it "has one initial journal and one non-initial journal" do expect(subject.first).to be_initial expect(subject.second).not_to be_initial end end - context 'when adding another change without comment' do + context "when adding another change without comment" do before do work_package.reload # need to update the lock_version, avoiding StaleObjectError - work_package.subject = 'foo' + work_package.subject = "foo" work_package.assigned_to = current_user work_package.save! end - it 'leads to a single journal with the comment of the replaced journal and the state both combined' do + it "leads to a single journal with the comment of the replaced journal and the state both combined" do expect(subject.count).to eq 1 expect(subject.first.notes) .to eql notes expect(subject.first.data.subject) - .to eql 'foo' + .to eql "foo" expect(subject.first.data.assigned_to) .to eql current_user @@ -700,16 +700,16 @@ end end - context 'when adding another change with a customized work package' do + context "when adding another change with a customized work package" do let(:custom_field) do create(:work_package_custom_field, is_required: false, - field_format: 'list', - possible_values: ['', '1', '2', '3', '4', '5', '6', '7']) + field_format: "list", + possible_values: ["", "1", "2", "3", "4", "5", "6", "7"]) end let(:custom_value) do create(:custom_value, - value: custom_field.custom_options.find { |co| co.value == '1' }.try(:id), + value: custom_field.custom_options.find { |co| co.value == "1" }.try(:id), customized: work_package, custom_field:) end @@ -717,66 +717,66 @@ before do custom_value work_package.reload # need to update the lock_version, avoiding StaleObjectError - work_package.subject = 'foo' + work_package.subject = "foo" work_package.save! end - it 'leads to a single journal with only one customizable journal' do + it "leads to a single journal with only one customizable journal" do expect(subject.count).to eq 1 expect(subject.first.notes) .to eql notes expect(subject.first.data.subject) - .to eql 'foo' + .to eql "foo" expect(subject.first.customizable_journals.count).to eq(1) end end end - it 'has the journal\'s creation time as the lower and no upper bound for validity_period' do + it "has the journal's creation time as the lower and no upper bound for validity_period" do expect(work_package.last_journal.validity_period) .to eql(work_package.last_journal.created_at...) end end - context 'with a different author' do + context "with a different author" do let(:new_author) { user2 } - it 'leads to two journals' do + it "leads to two journals" do expect(subject.count).to be 2 end - it 'has the initial user as the author of the first journal' do + it "has the initial user as the author of the first journal" do expect(subject.first.user) .to eql current_user end - it 'has the second user as he author of the second journal' do + it "has the second user as he author of the second journal" do expect(subject.second.user) .to eql new_author end - it 'has the changes (compared to the initial state) in the second journal' do + it "has the changes (compared to the initial state) in the second journal" do expect(subject.second.get_changes) .to eql("status_id" => [status.id, new_status.id]) end - it 'has the first journal\'s creation time as the lower and the second journal\'s creation time ' \ - 'as the upper bound for validity_period of the first journal' do + it "has the first journal's creation time as the lower and the second journal's creation time " \ + "as the upper bound for validity_period of the first journal" do expect(subject.first.validity_period) .to eql(subject.first.created_at...subject.second.created_at) end - it 'has the second journal\'s creation time as the lower and no upper bound for validity_period of the second journal' do + it "has the second journal's creation time as the lower and no upper bound for validity_period of the second journal" do expect(subject.second.validity_period) .to eql(subject.second.created_at...) end end end - context 'when updated after aggregation timeout expired', with_settings: { journal_aggregation_time_minutes: 1 } do + context "when updated after aggregation timeout expired", with_settings: { journal_aggregation_time_minutes: 1 } do let(:last_update_time) { 2.minutes.ago } subject(:journals) { work_package.journals } @@ -792,38 +792,38 @@ work_package.save! end - it 'creates a new journal' do + it "creates a new journal" do expect(journals.count).to be 2 end - it 'has the first journal\'s creation time as the lower and the second journal\'s creation time ' \ - 'as the upper bound for validity_period of the first journal' do + it "has the first journal's creation time as the lower and the second journal's creation time " \ + "as the upper bound for validity_period of the first journal" do expect(subject.first.validity_period) .to eql(subject.first.created_at...subject.second.created_at) end - it 'has the second journal\'s creation time as the lower and no upper bound for validity_period of the second journal' do + it "has the second journal's creation time as the lower and no upper bound for validity_period of the second journal" do expect(subject.second.validity_period) .to eql(subject.second.created_at...) end end - context 'when updating with aggregation disabled', with_settings: { journal_aggregation_time_minutes: 0 } do + context "when updating with aggregation disabled", with_settings: { journal_aggregation_time_minutes: 0 } do subject(:journals) { work_package.journals } - context 'when WP updated within milliseconds' do + context "when WP updated within milliseconds" do before do work_package.status = build(:status) work_package.save! end - it 'creates a new journal' do + it "creates a new journal" do expect(journals.count).to be 2 end end end - context 'when aggregation leads to an empty change (changing back and forth)', + context "when aggregation leads to an empty change (changing back and forth)", with_settings: { journal_aggregation_time_minutes: 1 } do let!(:work_package) do User.execute_as current_user do @@ -832,7 +832,7 @@ created_at: 5.minutes.ago, project_id: project.id, type:, - description: 'Description', + description: "Description", priority:, status:, duration: 1) @@ -848,17 +848,17 @@ work_package.save! end - it 'creates a new journal' do + it "creates a new journal" do expect(work_package.journals.count).to be 2 end - it 'has the old state in the last journal`s data' do + it "has the old state in the last journal`s data" do expect(work_package.journals.last.data.status_id).to be status.id end end end - describe '#destroy' do + describe "#destroy" do let(:project) { create(:project) } let(:type) { create(:type) } let(:custom_field) do @@ -887,27 +887,27 @@ work_package.destroy end - it 'removes the journal' do + it "removes the journal" do expect(Journal.find_by(id: journal.id)) .to be_nil end - it 'removes the journal data' do + it "removes the journal data" do expect(Journal::WorkPackageJournal.find_by(id: journal.data_id)) .to be_nil end - it 'removes the customizable journals' do + it "removes the customizable journals" do expect(Journal::CustomizableJournal.find_by(id: customizable_journals.map(&:id))) .to be_nil end - it 'removes the attachable journals' do + it "removes the attachable journals" do expect(Journal::AttachableJournal.find_by(id: attachable_journals.map(&:id))) .to be_nil end - it 'removes the storable journals' do + it "removes the storable journals" do expect(Journal::StorableJournal.find_by(id: attachable_journals.map(&:id))) .to be_nil end diff --git a/spec/services/projects/copy_service_integration_spec.rb b/spec/services/projects/copy_service_integration_spec.rb index 6e3e43935cff..513e95ec1d84 100644 --- a/spec/services/projects/copy_service_integration_spec.rb +++ b/spec/services/projects/copy_service_integration_spec.rb @@ -188,9 +188,9 @@ end end - context 'with disabled project custom fields with default value' do - it 'is still disabled in the copy' do - create(:text_project_custom_field, default_value: 'default value') + context "with disabled project custom fields with default value" do + it "is still disabled in the copy" do + create(:text_project_custom_field, default_value: "default value") expect(subject).to be_success diff --git a/spec/services/users/drop_tokens_service_spec.rb b/spec/services/users/drop_tokens_service_spec.rb index 5a4c93c030ce..84b08f926284 100644 --- a/spec/services/users/drop_tokens_service_spec.rb +++ b/spec/services/users/drop_tokens_service_spec.rb @@ -33,6 +33,7 @@ shared_let(:other_user) { create(:user) } let(:instance) { described_class.new(current_user: input_user) } + subject { instance.call! } describe "Invitation token" do diff --git a/spec/services/work_packages/set_schedule_service_spec.rb b/spec/services/work_packages/set_schedule_service_spec.rb index cbae618927a9..65e0f35d1139 100644 --- a/spec/services/work_packages/set_schedule_service_spec.rb +++ b/spec/services/work_packages/set_schedule_service_spec.rb @@ -26,14 +26,14 @@ # See COPYRIGHT and LICENSE files for more details. #++ -require 'spec_helper' +require "spec_helper" RSpec.describe WorkPackages::SetScheduleService do create_shared_association_defaults_for_work_package_factory let(:work_package) do create(:work_package, - subject: 'subject', + subject: "subject", start_date: work_package_start_date, due_date: work_package_due_date) end @@ -123,17 +123,17 @@ def create_child(parent, start_date, due_date) subject { instance.call(attributes) } - shared_examples_for 'reschedules' do + shared_examples_for "reschedules" do before do subject end - it 'is success' do + it "is success" do expect(subject) .to be_success end - it 'updates the following work packages' do + it "updates the following work packages" do expected.each do |wp, (start_date, due_date)| expected_cause_type = "work_package_related_changed_times" result = subject.all_results.find { |result_wp| result_wp.id == wp.id } @@ -168,87 +168,87 @@ def create_child(parent, start_date, due_date) end end - it 'returns only the original and the changed work packages' do + it "returns only the original and the changed work packages" do expect(subject.all_results) .to match_array expected.keys + [work_package] end end - shared_examples_for 'does not reschedule' do + shared_examples_for "does not reschedule" do before do subject end - it 'is success' do + it "is success" do expect(subject) .to be_success end - it 'does not change any other work packages' do + it "does not change any other work packages" do expect(subject.all_results) .to contain_exactly(work_package) end - it 'does not assign a journal cause' do + it "does not assign a journal cause" do subject.all_results.each do |work_package| expect(work_package.journal_cause).to be_blank end end end - context 'without relation' do - it 'is success' do + context "without relation" do + it "is success" do expect(subject) .to be_success end end - context 'with a single successor' do + context "with a single successor" do let!(:following) do [following_work_package1] end - context 'when moving forward' do + context "when moving forward" do before do work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 6.days, Time.zone.today + 8.days] } end end end - context 'when moving forward with the follower having no due date' do + context "when moving forward with the follower having no due date" do let(:follower1_due_date) { nil } before do work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 6.days, nil] } end end end - context 'when moving forward with the follower having no start date' do + context "when moving forward with the follower having no start date" do let(:follower1_start_date) { nil } before do work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 6.days, Time.zone.today + 6.days] } end end end - context 'when moving forward with the follower having some space left' do + context "when moving forward with the follower having some space left" do let(:follower1_start_date) { Time.zone.today + 3.days } let(:follower1_due_date) { Time.zone.today + 5.days } @@ -256,14 +256,14 @@ def create_child(parent, start_date, due_date) work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 6.days, Time.zone.today + 8.days] } end end end - context 'when moving forward with the follower having enough space left to not be moved at all' do + context "when moving forward with the follower having enough space left to not be moved at all" do let(:follower1_start_date) { Time.zone.today + 10.days } let(:follower1_due_date) { Time.zone.today + 12.days } @@ -271,10 +271,10 @@ def create_child(parent, start_date, due_date) work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" end - context 'when moving forward with the follower having some space left and a lag' do + context "when moving forward with the follower having some space left and a lag" do let(:follower1_start_date) { Time.zone.today + 5.days } let(:follower1_due_date) { Time.zone.today + 7.days } let(:follower1_lag) { 3 } @@ -283,14 +283,14 @@ def create_child(parent, start_date, due_date) work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 9.days, Time.zone.today + 11.days] } end end end - context 'when moving forward with the follower not needing to be moved' do + context "when moving forward with the follower not needing to be moved" do let(:follower1_start_date) { Time.zone.today + 6.days } let(:follower1_due_date) { Time.zone.today + 8.days } @@ -298,18 +298,18 @@ def create_child(parent, start_date, due_date) work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" end - context 'when moving backwards' do + context "when moving backwards" do before do work_package.due_date = Time.zone.today - 5.days end - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" end - context 'when moving backwards with space between' do + context "when moving backwards with space between" do let(:follower1_start_date) { Time.zone.today + 3.days } let(:follower1_due_date) { Time.zone.today + 5.days } @@ -317,7 +317,7 @@ def create_child(parent, start_date, due_date) work_package.due_date = Time.zone.today - 5.days end - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" end context 'when moving backwards with the follower having no start date (which should not happen) \ @@ -328,7 +328,7 @@ def create_child(parent, start_date, due_date) work_package.due_date = Time.zone.today - 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today - 4.days, follower1_due_date] } end @@ -343,82 +343,82 @@ def create_child(parent, start_date, due_date) work_package.due_date = follower1_due_date + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [follower1_due_date + 6.days, follower1_due_date + 6.days] } end end end - context 'when removing the dates on the predecessor' do + context "when removing the dates on the predecessor" do before do work_package.start_date = work_package.due_date = nil end # The follower will keep its dates - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" - context 'when the follower has no start date but a due date' do + context "when the follower has no start date but a due date" do let(:follower1_start_date) { nil } let(:follower1_due_date) { Time.zone.today + 15.days } - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" end end - context 'when not moving and the successor not having start & due date (e.g. creating relation)' do + context "when not moving and the successor not having start & due date (e.g. creating relation)" do let(:follower1_start_date) { nil } let(:follower1_due_date) { nil } - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [work_package.due_date + 1.day, nil] } end end end - context 'when not moving and the successor having due before predecessor due date (e.g. creating relation)' do + context "when not moving and the successor having due before predecessor due date (e.g. creating relation)" do let(:follower1_start_date) { nil } let(:follower1_due_date) { work_package_due_date - 5.days } - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [work_package.due_date + 1.day, work_package.due_date + 1.day] } end end end - context 'when not moving and the successor having start before predecessor due date (e.g. creating relation)' do + context "when not moving and the successor having start before predecessor due date (e.g. creating relation)" do let(:follower1_start_date) { work_package_due_date - 5.days } let(:follower1_due_date) { nil } - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [work_package.due_date + 1.day, nil] } end end end - context 'when not moving and the successor having start and due before predecessor due date (e.g. creating relation)' do + context "when not moving and the successor having start and due before predecessor due date (e.g. creating relation)" do let(:follower1_start_date) { work_package_due_date - 5.days } let(:follower1_due_date) { work_package_due_date - 2.days } - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [work_package.due_date + 1.day, work_package.due_date + 4.days] } end end end - context 'when not having dates and the successor not having start & due date (e.g. creating relation)' do + context "when not having dates and the successor not having start & due date (e.g. creating relation)" do let(:work_package_due_date) { nil } let(:follower1_start_date) { nil } let(:follower1_due_date) { nil } - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" end - context 'with the successor having another predecessor which has no dates' do + context "with the successor having another predecessor which has no dates" do let(:following_work_package1) do create_follower(follower1_start_date, follower1_due_date, @@ -431,29 +431,29 @@ def create_child(parent, start_date, due_date) due_date: nil) end - context 'when moving forward' do + context "when moving forward" do before do work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 6.days, Time.zone.today + 8.days] } end end end - context 'when moving backwards' do + context "when moving backwards" do before do work_package.due_date = Time.zone.today - 5.days end - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" end end end - context 'with only a parent' do + context "with only a parent" do let!(:parent_work_package) do create(:work_package).tap do |parent| work_package.parent = parent @@ -462,14 +462,14 @@ def create_child(parent, start_date, due_date) end let(:work_package_start_date) { Time.zone.today - 5.days } - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { parent_work_package => [work_package_start_date, work_package_due_date] } end end end - context 'with a parent having a follower' do + context "with a parent having a follower" do let(:work_package_start_date) { Time.zone.today } let(:work_package_due_date) { Time.zone.today + 5.days } let!(:parent_work_package) do @@ -487,7 +487,7 @@ def create_child(parent, start_date, due_date) { parent_work_package => 0 }) end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { parent_work_package => [work_package_start_date, work_package_due_date], follower_of_parent_work_package => [work_package_due_date + 1.day, work_package_due_date + 3.days] } @@ -514,7 +514,7 @@ def create_child(parent, start_date, due_date) # # That's why the WorkPackage.for_scheduling call is mocked to customize # the order of the returned work_packages to reproduce this bug. - context 'with also a sibling follower with same parent' do + context "with also a sibling follower with same parent" do let!(:sibling_follower_of_work_package) do create_follower(Time.zone.today + 2.days, Time.zone.today + 3.days, @@ -531,7 +531,7 @@ def create_child(parent, start_date, due_date) end end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { sibling_follower_of_work_package => [work_package_due_date + 1.day, work_package_due_date + 2.days], parent_work_package => [work_package_start_date, work_package_due_date + 2.days], @@ -541,18 +541,18 @@ def create_child(parent, start_date, due_date) end end - context 'with a single successor having a parent' do + context "with a single successor having a parent" do let!(:following) do [following_work_package1, parent_following_work_package1] end - context 'when moving forward' do + context "when moving forward" do before do work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 6.days, Time.zone.today + 8.days], parent_following_work_package1 => [Time.zone.today + 6.days, Time.zone.today + 8.days] } @@ -560,7 +560,7 @@ def create_child(parent, start_date, due_date) end end - context 'when moving forward with the parent having another child not being moved' do + context "when moving forward with the parent having another child not being moved" do let(:parent_follower1_start_date) { follower1_start_date } let(:parent_follower1_due_date) { follower1_due_date + 4.days } @@ -574,7 +574,7 @@ def create_child(parent, start_date, due_date) work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 6.days, Time.zone.today + 8.days], parent_following_work_package1 => [Time.zone.today + 5.days, Time.zone.today + 8.days] } @@ -582,16 +582,16 @@ def create_child(parent, start_date, due_date) end end - context 'when moving backwards' do + context "when moving backwards" do before do work_package.due_date = Time.zone.today - 5.days end - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" end end - context 'with a single successor having a child' do + context "with a single successor having a child" do let(:child_start_date) { follower1_start_date } let(:child_due_date) { follower1_due_date } @@ -602,12 +602,12 @@ def create_child(parent, start_date, due_date) child_work_package] end - context 'when moving forward' do + context "when moving forward" do before do work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 6.days, Time.zone.today + 8.days], child_work_package => [Time.zone.today + 6.days, Time.zone.today + 8.days] } @@ -616,7 +616,7 @@ def create_child(parent, start_date, due_date) end end - context 'with a single successor having two children' do + context "with a single successor having two children" do let(:follower1_start_date) { work_package_due_date + 1.day } let(:follower1_due_date) { work_package_due_date + 10.days } let(:child1_start_date) { follower1_start_date } @@ -633,11 +633,11 @@ def create_child(parent, start_date, due_date) child2_work_package] end - context 'with unchanged dates (e.g. when creating a follows relation) and successor starting 1 day after scheduled' do - it_behaves_like 'does not reschedule' + context "with unchanged dates (e.g. when creating a follows relation) and successor starting 1 day after scheduled" do + it_behaves_like "does not reschedule" end - context 'with unchanged dates (e.g. when creating a follows relation) and successor starting 3 days after scheduled' do + context "with unchanged dates (e.g. when creating a follows relation) and successor starting 3 days after scheduled" do let(:follower1_start_date) { work_package_due_date + 3.days } let(:follower1_due_date) { follower1_start_date + 10.days } let(:child1_start_date) { follower1_start_date } @@ -645,10 +645,10 @@ def create_child(parent, start_date, due_date) let(:child2_start_date) { follower1_start_date + 8.days } let(:child2_due_date) { follower1_due_date } - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" end - context 'with unchanged dates (e.g. when creating a follows relation) and successor\'s first child needs to be rescheduled' do + context "with unchanged dates (e.g. when creating a follows relation) and successor's first child needs to be rescheduled" do let(:follower1_start_date) { work_package_due_date - 3.days } let(:follower1_due_date) { work_package_due_date + 10.days } let(:child1_start_date) { follower1_start_date } @@ -657,7 +657,7 @@ def create_child(parent, start_date, due_date) let(:child2_due_date) { follower1_due_date } # following parent is reduced in length as the children allow to be executed at the same time - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [work_package_due_date + 1.day, follower1_due_date], child1_work_package => [work_package_due_date + 1.day, follower1_start_date + 10.days] } @@ -674,7 +674,7 @@ def create_child(parent, start_date, due_date) let(:child2_due_date) { follower1_due_date } # following parent is reduced in length and children are rescheduled - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [work_package_due_date + 1.day, follower1_start_date + 21.days], child1_work_package => [work_package_due_date + 1.day, child1_due_date + 9.days], @@ -684,7 +684,7 @@ def create_child(parent, start_date, due_date) end end - context 'with a chain of successors' do + context "with a chain of successors" do let(:follower1_start_date) { Time.zone.today + 1.day } let(:follower1_due_date) { Time.zone.today + 3.days } let(:follower2_start_date) { Time.zone.today + 4.days } @@ -698,12 +698,12 @@ def create_child(parent, start_date, due_date) following_work_package3] end - context 'when moving forward' do + context "when moving forward" do before do work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 6.days, Time.zone.today + 8.days], following_work_package2 => [Time.zone.today + 9.days, Time.zone.today + 13.days], @@ -712,7 +712,7 @@ def create_child(parent, start_date, due_date) end end - context 'when moving forward with some space between the followers' do + context "when moving forward with some space between the followers" do let(:follower1_start_date) { Time.zone.today + 1.day } let(:follower1_due_date) { Time.zone.today + 3.days } let(:follower2_start_date) { Time.zone.today + 7.days } @@ -724,7 +724,7 @@ def create_child(parent, start_date, due_date) work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 6.days, Time.zone.today + 8.days], following_work_package2 => [Time.zone.today + 9.days, Time.zone.today + 12.days] } @@ -732,16 +732,16 @@ def create_child(parent, start_date, due_date) end end - context 'when moving backwards' do + context "when moving backwards" do before do work_package.due_date = Time.zone.today - 5.days end - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" end end - context 'with a chain of successors with two paths leading to the same work package in the end' do + context "with a chain of successors with two paths leading to the same work package in the end" do let(:follower3_start_date) { Time.zone.today + 4.days } let(:follower3_due_date) { Time.zone.today + 7.days } let(:follower3_lag) { 0 } @@ -766,12 +766,12 @@ def create_child(parent, start_date, due_date) following_work_package4] end - context 'when moving forward' do + context "when moving forward" do before do work_package.due_date = Time.zone.today + 5.days end - it_behaves_like 'reschedules' do + it_behaves_like "reschedules" do let(:expected) do { following_work_package1 => [Time.zone.today + 6.days, Time.zone.today + 8.days], following_work_package2 => [Time.zone.today + 9.days, Time.zone.today + 13.days], @@ -781,16 +781,16 @@ def create_child(parent, start_date, due_date) end end - context 'when moving backwards' do + context "when moving backwards" do before do work_package.due_date = Time.zone.today - 5.days end - it_behaves_like 'does not reschedule' + it_behaves_like "does not reschedule" end end - context 'when setting the parent' do + context "when setting the parent" do let(:new_parent_work_package) { create(:work_package) } let(:attributes) { [:parent] } @@ -806,14 +806,14 @@ def create_child(parent, start_date, due_date) context "with the parent being restricted in its ability to be moved" do let(:soonest_date) { Time.zone.today + 3.days } - it 'sets the start date and due date to the earliest possible date' do + it "sets the start date and due date to the earliest possible date" do subject expect(work_package.start_date).to eql(Time.zone.today + 3.days) expect(work_package.due_date).to eql(Time.zone.today + 3.days) end - it 'does not change the due date if after the newly set start date' do + it "does not change the due date if after the newly set start date" do work_package.due_date = Time.zone.today + 5.days subject @@ -822,7 +822,7 @@ def create_child(parent, start_date, due_date) end end - context 'with the parent being restricted but work package already having dates set' do + context "with the parent being restricted but work package already having dates set" do let(:soonest_date) { Time.zone.today + 3.days } before do @@ -830,7 +830,7 @@ def create_child(parent, start_date, due_date) work_package.due_date = Time.zone.today + 5.days end - it 'sets the dates to provided dates' do + it "sets the dates to provided dates" do subject expect(work_package.start_date).to eql(Time.zone.today + 4.days) @@ -838,7 +838,7 @@ def create_child(parent, start_date, due_date) end end - context 'with the parent being restricted but the attributes define an earlier date' do + context "with the parent being restricted but the attributes define an earlier date" do let(:soonest_date) { Time.zone.today + 3.days } before do @@ -848,7 +848,7 @@ def create_child(parent, start_date, due_date) # This would be invalid but the dates should be set nevertheless # so we can have a correct error handling. - it 'sets the dates to provided dates' do + it "sets the dates to provided dates" do subject expect(work_package.start_date).to eql(Time.zone.today + 1.day) @@ -857,7 +857,7 @@ def create_child(parent, start_date, due_date) end end - context 'with deep hierarchy of work packages' do + context "with deep hierarchy of work packages" do before do work_package.due_date = Time.zone.today - 5.days end @@ -872,7 +872,7 @@ def create_hierarchy(parent, nb_children_by_levels) end end - it 'does not fail with a SystemStackError (regression #43894)' do + it "does not fail with a SystemStackError (regression #43894)" do parent = create(:work_package, start_date: Date.current, due_date: Date.current) hierarchy = [1, 1, 1, 1, 2, 4, 4, 4] create_hierarchy(parent, hierarchy) diff --git a/spec/support/components/projects/project_custom_fields/edit_dialog.rb b/spec/support/components/projects/project_custom_fields/edit_dialog.rb index 0250315b4441..80abf886e0a7 100644 --- a/spec/support/components/projects/project_custom_fields/edit_dialog.rb +++ b/spec/support/components/projects/project_custom_fields/edit_dialog.rb @@ -26,8 +26,8 @@ # See COPYRIGHT and LICENSE files for more details. # ++ -require 'support/components/common/modal' -require 'support/components/autocompleter/ng_select_autocomplete_helpers' +require "support/components/common/modal" +require "support/components/autocompleter/ng_select_autocomplete_helpers" module Components module Projects @@ -71,7 +71,7 @@ def close def close_via_button within(dialog_css_selector) do - click_link_or_button 'Cancel' + click_link_or_button "Cancel" end end @@ -96,8 +96,8 @@ def expect_async_content_loaded ### def input_containers - within '#project-section-edit-form > .FormControl-spacingWrapper' do - page.all('.FormControl-spacingWrapper') + within "#project-section-edit-form > .FormControl-spacingWrapper" do + page.all(".FormControl-spacingWrapper") end end diff --git a/spec/support/pages/notifications/center.rb b/spec/support/pages/notifications/center.rb index 6c0c0d7ac80f..f1b5c8283410 100644 --- a/spec/support/pages/notifications/center.rb +++ b/spec/support/pages/notifications/center.rb @@ -40,7 +40,7 @@ def path end def mark_all_read - click_button 'Mark all as read' + click_button "Mark all as read" end def mark_notification_as_read(notification) @@ -50,13 +50,13 @@ def mark_notification_as_read(notification) end def show_all - click_button 'All' + click_button "All" end def item_title(notification) text = notification.resource.is_a?(WorkPackage) ? notification.resource.subject : notification.subject within_item(notification) do - page.find('span', text:, exact_text: true) + page.find("span", text:, exact_text: true) end end @@ -111,15 +111,15 @@ def expect_work_package_item(*notifications) end def expect_closed - expect(page).to have_no_css('op-in-app-notification-center') + expect(page).to have_no_css("op-in-app-notification-center") end def expect_open - expect(page).to have_css('op-in-app-notification-center') + expect(page).to have_css("op-in-app-notification-center") end def expect_empty - expect(page).to have_text 'New notifications will appear here when there is activity that concerns you' + expect(page).to have_text "New notifications will appear here when there is activity that concerns you" end def expect_number_of_notifications(count) @@ -143,15 +143,15 @@ def bell_element end def expect_no_toaster - expect(page).to have_no_css('.op-toast.-info', wait: 10) + expect(page).to have_no_css(".op-toast.-info", wait: 10) end def expect_toast - expect(page).to have_css('.op-toast.-info', wait: 10) + expect(page).to have_css(".op-toast.-info", wait: 10) end def update_via_toaster - page.find('.op-toast.-info a', wait: 10).click + page.find(".op-toast.-info a", wait: 10).click end end end