Skip to content

Commit

Permalink
rewrite sql expectations
Browse files Browse the repository at this point in the history
  • Loading branch information
ulferts committed Jun 28, 2024
1 parent bcc622e commit 4bb80d7
Show file tree
Hide file tree
Showing 17 changed files with 704 additions and 449 deletions.
2 changes: 2 additions & 0 deletions app/models/queries/base_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ def apply_selects(query_scope)
selects.select { _1.respond_to?(:apply_to) }.inject(query_scope) do |scope, select|
# TODO: have all selects implement apply_to and use that to
# formulate the select clause
# * In case the select is on a column that is part of the model, the apply_to
# just returns the scope
select.apply_to(scope)
end
end
Expand Down
13 changes: 11 additions & 2 deletions app/models/queries/days/day_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ def default_scope
Day.default_scope
end

def results
super.reorder(date: :asc)
end

protected

##
# The dates interval filter needs to adjust the `from` clause of the query.
# If there are multiple filters with custom from clause (currently not possible),
Expand All @@ -49,7 +55,10 @@ def apply_filters(scope)
scope
end

def results
super.reorder(date: :asc)
# Since the model is a generated series, and the filters determine the range of that series,
# doing an EXISTS as done in the base query is not possible. The filtering determines the values that exists
# in the first place.
def filtered_results_scope
apply_filters(default_scope)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,83 @@
RSpec.describe Queries::TimeEntries::TimeEntryQuery, "integration" do
let(:instance) { described_class.new(user:) }

before do
login_as(user)
shared_let(:view_role) { create(:project_role, permissions: %i[log_own_time view_time_entries view_work_packages]) }
shared_let(:log_role) { create(:project_role, permissions: %i[log_own_time]) }
shared_let(:project) { create(:project, enabled_module_names: %w[costs work_package_tracking]) }
shared_let(:other_project) { create(:project, enabled_module_names: %w[costs work_package_tracking]) }
shared_let(:work_package) { create(:work_package, project:) }
shared_let(:other_work_package) { create(:work_package, project:) }
shared_let(:other_project_work_package) { create(:work_package, project: other_project) }
shared_let(:user) do
create(:user, member_with_roles: {
project => [view_role],
other_project => [log_role]
})
end
shared_let(:other_user) { create(:user, member_with_roles: { project => [log_role] }) }
shared_let(:time_entry) { create(:time_entry, user:, work_package:) }
shared_let(:other_user_time_entry) { create(:time_entry, user: other_user, work_package:) }
shared_let(:other_project_time_entry) { create(:time_entry, user:, work_package: other_project_work_package) }

context "when using ongoing filter" do
let(:project) { create(:project, enabled_module_names: %w[costs]) }
let(:user) { create(:user, member_with_permissions: { project => %i[log_own_time] }) }
let(:work_package) { create(:work_package, project:) }
let(:other_user) { create(:user, member_with_permissions: { project => %i[log_own_time] }) }
let(:other_work_package) { create(:work_package, project:) }
current_user { user }

let!(:user_timer) { create(:time_entry, user:, work_package:, ongoing: true) }
let!(:other_user_timer) { create(:time_entry, user: other_user, work_package: other_work_package, ongoing: true) }
describe "#results" do
subject { instance.results }

context "without a filter" do
it "returns all visible time_entries (sorted by id desc)" do
expect(subject).to eq([other_user_time_entry, time_entry])
end
end

context "with a user filter" do
before do
instance.where("user_id", "=", values)
end

context "with the value being for another user" do
let(:values) { [other_user.id.to_s] }

it "returns the entries of the filtered for user" do
expect(subject).to contain_exactly(other_user_time_entry)
end
end

context "with a me value" do
let(:values) { ["me"] }

it "returns the entries of the current user" do
expect(subject).to contain_exactly(time_entry)
end
end
end

context "with a project filter" do
before do
log_role.add_permission!(:view_time_entries)

instance.where("project_id", "=", [other_project.id.to_s])
end

it "returns only the time entries of the filtered for project" do
expect(subject).to contain_exactly(other_project_time_entry)
end
end

context "with a work_package filter" do
before do
instance.where("work_package_id", "=", [work_package.id.to_s])
end

it "returns only the time entries of the filtered for work_package" do
expect(subject).to contain_exactly(time_entry, other_user_time_entry)
end
end

context "when using ongoing filter" do
let!(:user_timer) { create(:time_entry, user:, work_package:, ongoing: true) }
let!(:other_user_timer) { create(:time_entry, user: other_user, work_package: other_work_package, ongoing: true) }

describe "#results" do
subject { instance.results }

before do
Expand All @@ -64,5 +126,15 @@
end
end
end

context "with an order by id asc" do
before do
instance.order(id: :asc)
end

it "returns all visible time entries ordered by id asc" do
expect(subject).to eq([time_entry, other_user_time_entry])
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,6 @@
login_as(user)
end

context "without a filter" do
describe "#results" do
it "is the same as getting all the time entries" do
expect(instance.results.to_sql).to eql base_scope.to_sql
end
end
end

context "with a user filter" do
let(:values) { ["1"] }

Expand All @@ -60,26 +52,6 @@
instance
end

describe "#results" do
it "is the same as handwriting the query" do
expected = base_scope
.where(["time_entries.user_id IN (?)", values])

expect(subject.results.to_sql).to eql expected.to_sql
end

context "with a me value" do
let(:values) { ["me"] }

it "replaces the value to produce the query" do
expected = base_scope
.where(["time_entries.user_id IN (?)", [user.id.to_s]])

expect(subject.results.to_sql).to eql expected.to_sql
end
end
end

describe "#valid?" do
it "is true" do
expect(subject).to be_valid
Expand Down Expand Up @@ -112,15 +84,6 @@
instance.where("project_id", "=", ["1"])
end

describe "#results" do
it "is the same as handwriting the query" do
expected = base_scope
.where(["time_entries.project_id IN (?)", ["1"]])

expect(instance.results.to_sql).to eql expected.to_sql
end
end

describe "#valid?" do
it "is true" do
expect(instance).to be_valid
Expand All @@ -142,15 +105,6 @@
instance.where("work_package_id", "=", ["1"])
end

describe "#results" do
it "is the same as handwriting the query" do
expected = base_scope
.where(["time_entries.work_package_id IN (?)", ["1"]])

expect(instance.results.to_sql).to eql expected.to_sql
end
end

describe "#valid?" do
it "is true" do
expect(instance).to be_valid
Expand All @@ -162,13 +116,4 @@
end
end
end

context "with an order by id asc" do
describe "#results" do
it "returns all visible time entries ordered by id asc" do
expect(instance.order(id: :asc).results.to_sql)
.to eql base_scope.except(:order).order(id: :asc).to_sql
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2010-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 Queries::Documents::DocumentQuery do
shared_let(:project) { create(:project) }
shared_let(:other_project) { create(:project) }
shared_let(:user) do
create(:user, member_with_permissions: {
project => %i[view_documents],
other_project => %i[view_documents]
})
end
shared_let(:document) { create(:document, project:) }
shared_let(:other_project_document) { create(:document, project: other_project) }
shared_let(:invisible_document) { create(:document) }

let(:instance) { described_class.new }

current_user { user }

describe "#results" do
subject { instance.results }

context "without a filter" do
it "is the same as getting all the visible documents (ordered by id asc)" do
expect(subject).to eq [other_project_document, document]
end
end

context "with a project filter" do
before do
instance.where("project_id", "=", [project.id])
end

it "returns the documents in the filtered for project" do
expect(subject).to eq [document]
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,7 @@
let(:base_scope) { Document.visible(user).order(id: :desc) }
let(:instance) { described_class.new }

before do
login_as(user)
end

context "without a filter" do
describe "#results" do
it "is the same as getting all the visible documents" do
expect(instance.results.to_sql).to eql base_scope.to_sql
end
end
end
current_user { user }

context "with a project filter" do
before do
Expand All @@ -54,15 +44,6 @@
instance.where("project_id", "=", ["1"])
end

describe "#results" do
it "is the same as handwriting the query" do
expected = base_scope
.where(["documents.project_id IN (?)", ["1"]])

expect(instance.results.to_sql).to eql expected.to_sql
end
end

describe "#valid?" do
it "is true" do
expect(instance).to be_valid
Expand Down
Loading

0 comments on commit 4bb80d7

Please sign in to comment.