mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-25 20:46:48 +00:00
325 lines
9.9 KiB
Ruby
325 lines
9.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'spec_helper'
|
|
|
|
# rubocop:disable Metrics/ModuleLength
|
|
module Reporting
|
|
RSpec.describe ReportTemplate do
|
|
let(:user) { create(:user) }
|
|
let(:params) { {} }
|
|
subject { described_class.new(user, params) }
|
|
|
|
# rubocop:disable Metrics/AbcSize
|
|
def check_report
|
|
# Mock using instance variables
|
|
allow(subject).to receive(:columns).and_return(@columns)
|
|
allow(subject).to receive(:query_result).and_return(@query_result)
|
|
allow(subject).to receive(:rules).and_return(@rules) if @rules.present?
|
|
if @custom_headers.present?
|
|
allow(subject).to receive(:custom_headers).and_return(@custom_headers)
|
|
end
|
|
|
|
# Check result depending on existing instance variables
|
|
expect(subject.rows.map(&:to_h)).to eq(@expected_rows) if @expected_rows.present?
|
|
expect(subject.table_rows).to eq(@expected_table_rows) if @expected_table_rows.present?
|
|
expect(subject.table_headers).to eq(@expected_headers) if @expected_headers.present?
|
|
end
|
|
# rubocop:enable Metrics/AbcSize
|
|
|
|
describe ".default_params" do
|
|
it "use correctly the default values" do
|
|
default_params = {
|
|
filter: "default__filter",
|
|
other_filter: "default_other_filter",
|
|
q: { hub: "default_hub", customer: "default_customer" }
|
|
}
|
|
real_params = {
|
|
filter: "test_filter",
|
|
q: { hub: "test_hub" }
|
|
}
|
|
expected_params = {
|
|
filter: "test_filter",
|
|
other_filter: "default_other_filter",
|
|
q: { hub: "test_hub", customer: "default_customer" }
|
|
}
|
|
allow_any_instance_of(described_class).to receive(:default_params)
|
|
.and_return(default_params)
|
|
report = described_class.new(user, real_params)
|
|
expect(report.params).to eq(expected_params)
|
|
end
|
|
end
|
|
|
|
describe ".columns" do
|
|
before do
|
|
@query_result = [
|
|
OpenStruct.new(hub: { name: "My Hub" }, product: { name: "Apple", price: 5 })
|
|
]
|
|
end
|
|
|
|
it "handle procs" do
|
|
@columns = {
|
|
hub: proc { |item| item.hub[:name] }
|
|
}
|
|
@expected_rows = [
|
|
{ hub: "My Hub" }
|
|
]
|
|
check_report
|
|
end
|
|
|
|
it "handles symbols" do
|
|
@columns = {
|
|
hub: :hub_name
|
|
}
|
|
allow(subject).to receive(:hub_name).and_return("Transformed Hub Name")
|
|
@expected_rows = [
|
|
{ hub: "Transformed Hub Name" }
|
|
]
|
|
check_report
|
|
end
|
|
end
|
|
|
|
describe ".table_headers" do
|
|
before do
|
|
@columns = {
|
|
hub: proc { |item| item.hub[:name] },
|
|
product: proc { |item| item.product[:name] },
|
|
price: proc { |item| item.product[:price] },
|
|
}
|
|
end
|
|
|
|
it "uses the columns keys" do
|
|
@expected_headers = ['Hub', 'Product', 'Price']
|
|
check_report
|
|
end
|
|
|
|
it "handles custom_headers" do
|
|
@custom_headers = {
|
|
product: 'Custom Product',
|
|
not_existing_key: "My Key"
|
|
}
|
|
@expected_headers = ['Hub', 'Custom Product', 'Price']
|
|
check_report
|
|
end
|
|
|
|
describe "fields_to_show" do
|
|
let(:params) { { fields_to_show: [:hub, :price] } }
|
|
|
|
it "works" do
|
|
@expected_headers = ['Hub', 'Price']
|
|
check_report
|
|
end
|
|
end
|
|
end
|
|
|
|
describe ".table_rows" do
|
|
before do
|
|
@columns = {
|
|
price: proc { |item| item.product[:price] },
|
|
hub: proc { |item| item.hub[:name] }
|
|
}
|
|
@query_result = [
|
|
OpenStruct.new(hub: { name: "My Hub" }, product: { name: "Apple", price: 5 }),
|
|
OpenStruct.new(hub: { name: "My Other Hub" }, product: { name: "Apple", price: 12 })
|
|
]
|
|
end
|
|
|
|
it "get correct data" do
|
|
allow(subject).to receive(:unformatted_render?).and_return(true)
|
|
@expected_table_rows = [
|
|
[5, "My Hub"],
|
|
[12, "My Other Hub"],
|
|
]
|
|
check_report
|
|
end
|
|
|
|
context "when report contains duplicate rows" do
|
|
before do
|
|
@columns = {
|
|
customer: proc { |item| item.customer },
|
|
address: proc { |item| item.address }
|
|
}
|
|
@query_result = [
|
|
OpenStruct.new(customer: "John", address: "1 Main Street"),
|
|
OpenStruct.new(customer: "John", address: "1 Main Street")
|
|
]
|
|
end
|
|
|
|
context "and the report type allows duplicate rows i.e. the default behaviour" do
|
|
it "outputs duplicate rows" do
|
|
@expected_table_rows = [
|
|
["John", "1 Main Street"],
|
|
["John", "1 Main Street"]
|
|
]
|
|
check_report
|
|
end
|
|
end
|
|
|
|
context "and the report type does not allow duplicate rows" do
|
|
before { allow(subject).to receive(:skip_duplicate_rows?).and_return(true) }
|
|
|
|
it "outputs only unique rows" do
|
|
@expected_table_rows = [
|
|
["John", "1 Main Street"]
|
|
]
|
|
check_report
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe ".rules" do
|
|
describe "#group_by" do
|
|
before do
|
|
@columns = {
|
|
hub: proc { |item| item.hub },
|
|
customer: proc { |item| item.customer },
|
|
product: proc { |item| item.product },
|
|
quantity: proc { |item| item.quantity },
|
|
}
|
|
@query_result = [
|
|
OpenStruct.new(hub: "Hub 1", customer: "John", product: "Apple", quantity: 4),
|
|
OpenStruct.new(hub: "Hub 2", customer: "John", product: "Pear", quantity: 3),
|
|
OpenStruct.new(hub: "Hub 2", customer: "John", product: "Apple", quantity: 5),
|
|
OpenStruct.new(hub: "Hub 1", customer: "Abby", product: "Orange", quantity: 6),
|
|
]
|
|
end
|
|
|
|
it "works with symbol or proc" do
|
|
@rules = [
|
|
{ group_by: proc { |_i, row| row.hub }, fields_used_in_header: [:hub], header: true },
|
|
{ group_by: :customer, header: true }
|
|
]
|
|
allow(subject).to receive(:display_header_row?).and_return(true)
|
|
@expected_rows = [
|
|
{ header: "Hub 1" },
|
|
{ header: "Abby" },
|
|
{ product: "Orange", quantity: 6 },
|
|
{ header: "John" },
|
|
{ product: "Apple", quantity: 4 },
|
|
{ header: "Hub 2" },
|
|
{ header: "John" },
|
|
{ product: "Pear", quantity: 3 },
|
|
{ product: "Apple", quantity: 5 },
|
|
]
|
|
check_report
|
|
end
|
|
end
|
|
|
|
describe "#sort_by" do
|
|
before do
|
|
@columns = {
|
|
hub_name: proc { |item| item.hub[:name] }
|
|
}
|
|
hub1 = { name: "Hub 1", popularity: 5 }
|
|
hub2 = { name: "Hub 2", popularity: 2 }
|
|
@query_result = [
|
|
OpenStruct.new(hub: hub2),
|
|
OpenStruct.new(hub: hub1)
|
|
]
|
|
end
|
|
|
|
it "use default sort" do
|
|
@rules = [{
|
|
group_by: proc { |item, _row| item.hub }
|
|
}]
|
|
@expected_rows = [
|
|
{ hub_name: "Hub 1" },
|
|
{ hub_name: "Hub 2" },
|
|
]
|
|
check_report
|
|
end
|
|
|
|
it "use sort_by proc" do
|
|
@rules = [{
|
|
group_by: proc { |item, _row| item.hub },
|
|
sort_by: proc { |hub| hub[:popularity] }
|
|
}]
|
|
@expected_rows = [
|
|
{ hub_name: "Hub 2" },
|
|
{ hub_name: "Hub 1" }
|
|
]
|
|
check_report
|
|
end
|
|
end
|
|
|
|
describe "#summary_row" do
|
|
before do
|
|
@query_result = [
|
|
OpenStruct.new(hub: "Hub 1", customer: "John", product: "Apple", quantity: 4),
|
|
OpenStruct.new(hub: "Hub 2", customer: "John", product: "Pear", quantity: 3),
|
|
OpenStruct.new(hub: "Hub 2", customer: "John", product: "Apple", quantity: 5),
|
|
OpenStruct.new(hub: "Hub 1", customer: "Abby", product: "Orange", quantity: 6),
|
|
]
|
|
end
|
|
|
|
it "groups and sum" do
|
|
@columns = {
|
|
hub: proc { |item| item.hub },
|
|
quantity: proc { |item| item.quantity },
|
|
count: proc { |_item| "" },
|
|
}
|
|
@rules = [{
|
|
group_by: :hub,
|
|
summary_row: proc do |group_key, items, rows|
|
|
{ count: "#{group_key} count=#{items.count}", quantity: rows.sum(&:quantity) }
|
|
end,
|
|
summary_row_label: "TOTAL"
|
|
}]
|
|
@expetec_rows = [
|
|
{ hub: "Hub 1", quantity: 4, count: "" },
|
|
{ hub: "Hub 1", quantity: 6, count: "" },
|
|
{ hub: "TOTAL", quantity: 10, count: "Hub 1 count=2" },
|
|
{ hub: "Hub 2", quantity: 3, count: "" },
|
|
{ hub: "Hub 2", quantity: 5, count: "" },
|
|
{ hub: "TOTAL", quantity: 8, count: "Hub 2 count=2" }
|
|
]
|
|
check_report
|
|
end
|
|
end
|
|
|
|
describe "should not group when for JSON" do
|
|
before do
|
|
@query_result = [
|
|
OpenStruct.new(hub: "Hub 1", customer: "John", quantity: 4)
|
|
]
|
|
@columns = {
|
|
hub: proc { |item| item.hub },
|
|
customer: proc { |item| item.customer },
|
|
quantity: proc { |item| item.quantity },
|
|
}
|
|
@rules = [{
|
|
group_by: :hub,
|
|
header: true,
|
|
summary_row: proc do |_group_key, _items, rows|
|
|
{ quantity: rows.sum(&:quantity) }
|
|
end
|
|
}]
|
|
end
|
|
|
|
describe "for fields_to_show" do
|
|
let(:params) { { fields_to_show: [:hub, :quantity], report_format: 'json' } }
|
|
|
|
it "works" do
|
|
@expetec_rows = [
|
|
{ hub: "Hub 1", quantity: 4 }
|
|
]
|
|
check_report
|
|
end
|
|
end
|
|
|
|
describe "for fields_to_hide" do
|
|
let(:params) { { fields_to_hide: [:customer], report_format: 'json' } }
|
|
|
|
it "works" do
|
|
@expetec_rows = [
|
|
{ hub: "Hub 1", quantity: 4 }
|
|
]
|
|
check_report
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
# rubocop:enable Metrics/ModuleLength
|