rubocop autocorrect

This commit is contained in:
Ivan Kuchin
2024-06-24 19:01:59 +02:00
parent 32d4a2c727
commit b10e6d718c
43 changed files with 549 additions and 551 deletions
@@ -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
+3 -3
View File
@@ -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
##
-1
View File
@@ -40,7 +40,6 @@ class Project < ApplicationRecord
include ::Scopes::Scoped
# Maximum length for project identifiers
IDENTIFIER_MAX_LENGTH = 100
+2 -2
View File
@@ -133,7 +133,7 @@ class Setting < ApplicationRecord
private
def accessor_base_name(name)
name.to_s.sub(/(_writable\?)|(\?)|=\z/, '')
name.to_s.sub(/(_writable\?)|(\?)|=\z/, "")
end
end
@@ -337,7 +337,7 @@ class Setting < ApplicationRecord
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
@@ -77,16 +77,16 @@ module WorkPackage::Exports
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 @@ module WorkPackage::Exports
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)
+2 -1
View File
@@ -99,8 +99,9 @@ module Projects
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
@@ -65,7 +65,7 @@ module Users
def invalidate_tokens
::Users::DropTokensService
.new(current_user: current_user)
.new(current_user:)
.call!
end
+2 -2
View File
@@ -46,11 +46,11 @@ module Users
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
@@ -42,7 +42,7 @@ class AddLdapTlsOptions < ActiveRecord::Migration[7.0]
# 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 @@ class AddLdapTlsOptions < ActiveRecord::Migration[7.0]
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
@@ -3,6 +3,6 @@ class RenameDelayToLag < ActiveRecord::Migration[7.1]
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
@@ -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
@@ -9,7 +9,7 @@ module Primer
options.reverse_merge!(
component: "opce-project-autocompleter",
defaultData: false,
filters: [{ name: 'active', operator: '=', values: ['t'] }],
filters: [{ name: "active", operator: "=", values: ["t"] }]
)
if options[:disabledProjects]
@@ -42,7 +42,7 @@ module Acts::Journalized
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 @@ module Acts::Journalized
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 @@ module Acts::Journalized
if selected_journals.empty?
nil
else
selected_journals.sort.join(',')
selected_journals.sort.join(",")
end
end
end
@@ -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
@@ -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
@@ -65,15 +65,14 @@ RSpec.describe "Calendar Widget", :js, :with_cuprite, with_settings: { start_of_
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
+1 -1
View File
@@ -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
@@ -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 @@ class Activities::MeetingActivityProvider < Activities::BaseActivityProvider
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 @@ class Activities::MeetingActivityProvider < Activities::BaseActivityProvider
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 @@ class Activities::MeetingActivityProvider < Activities::BaseActivityProvider
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 @@ class Activities::MeetingActivityProvider < Activities::BaseActivityProvider
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 @@ class Activities::MeetingActivityProvider < Activities::BaseActivityProvider
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 @@ class Activities::MeetingActivityProvider < Activities::BaseActivityProvider
end
def activity_id(event)
activity == :meeting ? event['journable_id'] : event['meeting_id']
activity == :meeting ? event["journable_id"] : event["meeting_id"]
end
end
@@ -48,7 +48,7 @@ RSpec.describe Meetings::CopyService, "integration", type: :model do
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
+1 -1
View File
@@ -31,7 +31,7 @@ class Widget::CostTypes < Widget::Base
@cost_types = options.delete(:cost_types)
@selected_type_id = options.delete(:selected_type_id)
super(options, &)
super
end
def render
@@ -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
@@ -33,7 +33,7 @@ require_module_spec_helper
# 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 @@ RSpec.describe "Delete ProjectStorage with FileLinks", :js, :with_cuprite, :webm
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
@@ -74,7 +74,7 @@ RSpec.describe "Hide attachments", :js, :with_cuprite do
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 @@ RSpec.describe "Hide attachments", :js, :with_cuprite do
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
@@ -38,10 +38,7 @@ require_module_spec_helper
# 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 @@ RSpec.describe("Activation of storages in projects",
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 @@ RSpec.describe("Activation of storages in projects",
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 @@ RSpec.describe("Activation of storages in projects",
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 @@ RSpec.describe("Activation of storages in projects",
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 @@ RSpec.describe("Activation of storages in projects",
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",
@@ -75,7 +75,7 @@ RSpec.describe "OAuth Access Grant Nudge upon adding a storage to a project",
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
@@ -79,7 +79,7 @@ RSpec.describe Members::RoleFormComponent, type: :component do
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
@@ -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
@@ -53,7 +53,7 @@ RSpec.describe "Link custom fields edit", :js, :with_cuprite do
# 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
@@ -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 @@ RSpec.describe 'List project custom fields', :js do
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 @@ RSpec.describe 'List project custom fields', :js do
# 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 @@ RSpec.describe 'List project custom fields', :js do
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 @@ RSpec.describe 'List project custom fields', :js do
.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 @@ RSpec.describe 'List project custom fields', :js do
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 @@ RSpec.describe 'List project custom fields', :js do
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 @@ RSpec.describe 'List project custom fields', :js do
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 @@ RSpec.describe 'List project custom fields', :js do
# 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 @@ RSpec.describe 'List project custom fields', :js do
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 @@ RSpec.describe 'List project custom fields', :js do
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 @@ RSpec.describe 'List project custom fields', :js do
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 @@ RSpec.describe 'List project custom fields', :js do
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 @@ RSpec.describe 'List project custom fields', :js do
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
+1
View File
@@ -44,6 +44,7 @@ RSpec.describe "Favorite projects", :js do
let(:my_page) do
Pages::My::Page.new
end
context "as a user" do
before do
login_as user
@@ -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 @@ RSpec.describe 'Edit project custom fields on project overview page', :js do
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
@@ -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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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 @@ RSpec.describe 'Projects custom fields mapping via project settings', :js, :with
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, &)
+8 -7
View File
@@ -234,15 +234,16 @@ RSpec.describe "work package export" do
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 @@ RSpec.describe "work package export" do
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 @@ RSpec.describe "work package export" do
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
@@ -31,34 +31,7 @@ require "spec_helper"
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 @@ RSpec.describe "Wysiwyg attribute macros", :js do
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
+9 -9
View File
@@ -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
+9 -9
View File
@@ -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 @@ RSpec.describe I18n do
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 @@ RSpec.describe I18n do
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"
@@ -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) }
@@ -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 @@ RSpec.describe WorkPackage do
create(:work_package,
project_id: project.id,
type:,
description: 'Description',
description: "Description",
priority:,
status:,
duration: 1)
@@ -52,53 +52,53 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
})
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
.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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
created_at: 5.minutes.ago,
project_id: project.id,
type:,
description: 'Description',
description: "Description",
priority:,
status:,
duration: 1)
@@ -848,17 +848,17 @@ RSpec.describe WorkPackage do
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 @@ RSpec.describe WorkPackage do
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
@@ -188,9 +188,9 @@ RSpec.describe(
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
@@ -33,6 +33,7 @@ RSpec.describe Users::DropTokensService, type: :model do
shared_let(:other_user) { create(:user) }
let(:instance) { described_class.new(current_user: input_user) }
subject { instance.call! }
describe "Invitation token" do
@@ -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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService 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 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 @@ RSpec.describe WorkPackages::SetScheduleService 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 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 @@ RSpec.describe WorkPackages::SetScheduleService 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 + 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 @@ RSpec.describe WorkPackages::SetScheduleService 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' 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 @@ RSpec.describe WorkPackages::SetScheduleService 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 the follower having no start date (which should not happen) \
@@ -328,7 +328,7 @@ RSpec.describe WorkPackages::SetScheduleService 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 - 4.days, follower1_due_date] }
end
@@ -343,82 +343,82 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
{ 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 @@ RSpec.describe WorkPackages::SetScheduleService do
#
# 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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService 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 + 5.days, Time.zone.today + 8.days] }
@@ -582,16 +582,16 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService 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 + 12.days] }
@@ -732,16 +732,16 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
# 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 @@ RSpec.describe WorkPackages::SetScheduleService do
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 @@ RSpec.describe WorkPackages::SetScheduleService do
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)
@@ -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 @@ module Components
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 @@ module Components
###
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
+9 -9
View File
@@ -40,7 +40,7 @@ module Pages
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 @@ module Pages
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 @@ module Pages
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 @@ module Pages
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