mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
Add component specs
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) 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 "rails_helper"
|
||||
|
||||
RSpec.describe QuickFilter::BooleanComponent, type: :component do
|
||||
include QuickFilterHelpers
|
||||
|
||||
let(:project) { build_stubbed(:project) }
|
||||
let(:query) { build_meeting_query }
|
||||
|
||||
subject(:component) do
|
||||
described_class.new(
|
||||
name: "Boolean filter",
|
||||
query:,
|
||||
filter_key: :type,
|
||||
true_label: "Yes",
|
||||
false_label: "No",
|
||||
path_args: [project, :meetings]
|
||||
)
|
||||
end
|
||||
|
||||
context "when rendering" do
|
||||
before { render_inline(component) }
|
||||
|
||||
it "renders both items with the provided labels" do
|
||||
expect(page).to have_text("Yes")
|
||||
expect(page).to have_text("No")
|
||||
end
|
||||
|
||||
it "renders exactly two items" do
|
||||
expect(page).to have_css("a", count: 2)
|
||||
end
|
||||
|
||||
it "uses 't' and 'f' as filter values" do
|
||||
expect(filters_from_link(page.find("a", text: "Yes")))
|
||||
.to include({ "type" => { "operator" => "=", "values" => ["t"] } })
|
||||
expect(filters_from_link(page.find("a", text: "No")))
|
||||
.to include({ "type" => { "operator" => "=", "values" => ["f"] } })
|
||||
end
|
||||
end
|
||||
|
||||
context "when the true value is active" do
|
||||
let(:query) { build_meeting_query.where("type", "=", ["t"]) }
|
||||
|
||||
before do
|
||||
render_inline(component)
|
||||
end
|
||||
|
||||
it "marks the true item as selected" do
|
||||
expect(page).to have_css("[aria-current='true']", text: "Yes")
|
||||
end
|
||||
|
||||
it "does not mark the false item as selected" do
|
||||
expect(page).to have_no_css("[aria-current='true']", text: "No")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,153 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) 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 "rails_helper"
|
||||
|
||||
RSpec.describe QuickFilter::SegmentedComponent, type: :component do
|
||||
include QuickFilterHelpers
|
||||
|
||||
let(:project) { build_stubbed(:project) }
|
||||
let(:query) { build_meeting_query }
|
||||
let(:orders) { nil }
|
||||
|
||||
subject(:component) do
|
||||
described_class.new(
|
||||
name: "Test filter",
|
||||
query:,
|
||||
filter_key: :time,
|
||||
path_args: [project, :meetings],
|
||||
orders:
|
||||
)
|
||||
end
|
||||
|
||||
context "when rendering with items" do
|
||||
before do
|
||||
render_inline(component) do |c|
|
||||
c.with_item(label: "Upcoming", value: "future")
|
||||
c.with_item(label: "Past", value: "past")
|
||||
end
|
||||
end
|
||||
|
||||
it "renders all items" do
|
||||
expect(page).to have_text("Upcoming")
|
||||
expect(page).to have_text("Past")
|
||||
end
|
||||
|
||||
it "renders a segmented control" do
|
||||
expect(page).to have_css("segmented-control [aria-label='Test filter']")
|
||||
end
|
||||
end
|
||||
|
||||
context "when no items are given" do
|
||||
before do
|
||||
render_inline(component)
|
||||
end
|
||||
|
||||
it "does not render" do
|
||||
expect(page).to have_no_css("segmented-control [aria-label='Test filter']")
|
||||
end
|
||||
end
|
||||
|
||||
context "when an item matches the active filter value" do
|
||||
let(:query) { build_meeting_query.where("time", "=", ["future"]) }
|
||||
|
||||
before do
|
||||
render_inline(component) do |c|
|
||||
c.with_item(label: "Upcoming", value: "future")
|
||||
c.with_item(label: "Past", value: "past")
|
||||
end
|
||||
end
|
||||
|
||||
it "marks the matching item as selected" do
|
||||
expect(page).to have_css("[aria-current='true']", text: "Upcoming")
|
||||
end
|
||||
|
||||
it "does not mark the other item as selected" do
|
||||
expect(page).to have_no_css("[aria-current='true']", text: "Past")
|
||||
end
|
||||
end
|
||||
|
||||
context "when no filter is active" do
|
||||
before do
|
||||
render_inline(component) do |c|
|
||||
c.with_item(label: "All", value: nil)
|
||||
c.with_item(label: "Upcoming", value: "future")
|
||||
c.with_item(label: "Past", value: "past")
|
||||
end
|
||||
end
|
||||
|
||||
it "marks the nil value item as selected" do
|
||||
expect(page).to have_css("[aria-current='true']", text: "All")
|
||||
end
|
||||
end
|
||||
|
||||
context "when other filters are active" do
|
||||
let(:query) { build_meeting_query.where("time", "=", ["future"]) }
|
||||
|
||||
subject(:component) do
|
||||
described_class.new(
|
||||
name: "Type filter",
|
||||
query:,
|
||||
filter_key: :type,
|
||||
path_args: [project, :meetings]
|
||||
)
|
||||
end
|
||||
|
||||
before do
|
||||
render_inline(component) do |c|
|
||||
c.with_item(label: "All", value: nil)
|
||||
c.with_item(label: "One-time", value: "f")
|
||||
c.with_item(label: "Recurring", value: "t")
|
||||
end
|
||||
end
|
||||
|
||||
it "excludes the target filter when value is nil, leaving others unchanged" do
|
||||
filter_keys = filters_from_link(page.find("a", text: "All")).map { |f| f.keys.first }
|
||||
|
||||
expect(filter_keys).to include("time")
|
||||
expect(filter_keys).not_to include("type")
|
||||
end
|
||||
end
|
||||
|
||||
context "with order overrides" do
|
||||
let(:orders) { { "future" => { start_time: :asc }, "past" => { start_time: :desc } } }
|
||||
|
||||
before do
|
||||
render_inline(component) do |c|
|
||||
c.with_item(label: "Upcoming", value: "future")
|
||||
c.with_item(label: "Past", value: "past")
|
||||
end
|
||||
end
|
||||
|
||||
it "uses the override sort for the matching value" do
|
||||
expect(sort_from_link(page.find("a", text: "Past"))).to eq([["start_time", "desc"]])
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
#-- copyright
|
||||
# OpenProject is an open source project management software.
|
||||
# Copyright (C) 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.
|
||||
#++
|
||||
|
||||
module QuickFilterHelpers
|
||||
def build_meeting_query(user: build_stubbed(:user))
|
||||
Queries::Meetings::MeetingQuery.new(user:)
|
||||
end
|
||||
|
||||
def filters_from_link(link)
|
||||
json = CGI.unescape(link[:href].match(/filters=([^&]+)/)[1])
|
||||
JSON.parse(json)
|
||||
end
|
||||
|
||||
def sort_from_link(link)
|
||||
json = CGI.unescape(link[:href].match(/sortBy=([^&]+)/)[1])
|
||||
JSON.parse(json)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user