Skip to content

Commit

Permalink
Add feature specs for possible modal scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
aaron-contreras committed Apr 4, 2024
1 parent e181e52 commit 85d9fd6
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 1 deletion.
140 changes: 140 additions & 0 deletions spec/features/work_packages/progress_modal_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# frozen_string_literal: true

# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2024 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
# ++

require "spec_helper"

RSpec.describe "Progress modal", :js, :with_cuprite do
shared_let(:user) { create(:admin) }
shared_let(:project) { create(:project) }

shared_let(:estimated_hours) { 10.0 }
shared_let(:remaining_hours) { 5.0 }
shared_let(:work_package) do
create(:work_package, project:) do |wp|
update_work_package_with(wp, estimated_hours:, remaining_hours:)
end
end

def update_work_package_with(work_package, attributes)
WorkPackages::UpdateService.new(model: work_package,
user:,
contract_class: WorkPackages::CreateContract)
.call(**attributes)
end

current_user { user }

let(:progress_query) do
create(:query,
project:,
user:,
display_sums: false,
column_names: %i[id subject type status
estimated_hours remaining_hours done_ratio]) do |query|
create(:view_work_packages_table, query:)
end
end
let(:work_package_table) { Pages::WorkPackagesTable.new(project) }
let(:work_package_row) { work_package_table.work_package_container(work_package) }

describe "clicking on a field on the work package table" do
it "opens the modal with its work field in focus " \
"when clicking on the work input field" do
work_package_table.visit_query(progress_query)
work_package_table.expect_work_package_listed(work_package)

work_edit_field = ProgressEditField.new(work_package_row, :estimatedTime)
modal = work_edit_field.activate!

modal.expect_modal_field_in_focus
end

it "sets the cursor after the last character on the selected input field" do
work_package_table.visit_query(progress_query)
work_package_table.expect_work_package_listed(work_package)

work_edit_field = ProgressEditField.new(work_package_row, :estimatedTime)
modal = work_edit_field.activate!

modal.expect_cursor_at_end_of_input
end
end

describe "clicking on the remaining work field on the work package table " \
"with no fields set" do
before do
update_work_package_with(work_package, estimated_hours: nil, remaining_hours: nil)
end

it "opens the modal with work in focus and remaining work disabled" do
work_package_table.visit_query(progress_query)
work_package_table.expect_work_package_listed(work_package)

work_edit_field = ProgressEditField.new(work_package_row, :estimatedTime)
remaining_work_field = ProgressEditField.new(work_package_row, :remainingTime)

remaining_work_field.activate!

work_edit_field.expect_modal_field_in_focus
remaining_work_field.expect_modal_field_disabled
end
end

describe "opening the progress modal" do
it "populates fields with correct values" do
work_package_table.visit_query(progress_query)
work_package_table.expect_work_package_listed(work_package)

work_edit_field = ProgressEditField.new(work_package_row, :estimatedTime)
remaining_work_edit_field = ProgressEditField.new(work_package_row, :remainingTime)
percent_complete_edit_field = ProgressEditField.new(work_package_row, :percentageDone)

work_edit_field.activate!

work_edit_field.expect_modal_field_value(work_package.estimated_hours)
remaining_work_edit_field.expect_modal_field_value(work_package.remaining_hours)
percent_complete_edit_field.expect_modal_field_value(work_package.done_ratio)
end
end

describe "% Complete field" do
it "renders as readonly" do
work_package_table.visit_query(progress_query)
work_package_table.expect_work_package_listed(work_package)

work_edit_field = ProgressEditField.new(work_package_row, :estimatedTime)
percent_complete_edit_field = ProgressEditField.new(work_package_row, :percentageDone)

work_edit_field.activate!

percent_complete_edit_field.expect_read_only_modal_field
end
end
end
3 changes: 3 additions & 0 deletions spec/support/edit_fields/edit_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ def expect_display_value(value)

##
# Activate the field and check it opened correctly
# @return [EditField] self
def activate!(expect_open: true)
retry_block(args: { tries: 2 }) do
unless active?
Expand All @@ -99,6 +100,8 @@ def activate!(expect_open: true)
if expect_open && !active?
raise "Expected field for attribute '#{property_name}' to be active."
end

self
end
end

Expand Down
31 changes: 30 additions & 1 deletion spec/support/edit_fields/progress_edit_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ class ProgressEditField < EditField
MODAL_SELECTOR = "#work_package_progress_modal"
FIELD_NAME_MAP = {
"estimatedTime" => :estimated_hours,
"remainingTime" => :remaining_hours
"remainingTime" => :remaining_hours,
"percentageDone" => :done_ratio
}.freeze

def initialize(context,
Expand Down Expand Up @@ -89,6 +90,34 @@ def display_selector
end
end

# Checks if the modal field is in focus.
# It compares the active element in the page (the element in focus) with the input element of the modal.
# If they are the same, it means the modal field is in focus.
# @return [Boolean] true if the modal field is in focus, false otherwise.
def expect_modal_field_in_focus
input_element == page.evaluate_script("document.activeElement")
end

# Checks if the cursor is at the end of the input in the modal field.
# It compares the cursor position (selectionStart) with the length of the value in the input field.
# If they are the same, it means the cursor is at the end of the input.
# @return [Boolean] true if the cursor is at the end of the input, false otherwise.
def expect_cursor_at_end_of_input
input_element.evaluate_script("this.selectionStart == this.value.length;")
end

def expect_modal_field_disabled
expect(page).to have_field(@field_name, disabled: true)
end

def expect_read_only_modal_field
expect(input_element).to be_readonly
end

def expect_modal_field_value(value)
expect(input_element.value).to eq(value.to_s)
end

private

attr_reader :field_name
Expand Down

0 comments on commit 85d9fd6

Please sign in to comment.