diff --git a/lib/liquid/standardfilters.rb b/lib/liquid/standardfilters.rb index 661235a9d..0fcd55e58 100644 --- a/lib/liquid/standardfilters.rb +++ b/lib/liquid/standardfilters.rb @@ -892,9 +892,11 @@ def sum(input, property = nil) raise_property_error(property) end - InputIterator.new(values_for_sum, context).sum do |item| + result = InputIterator.new(values_for_sum, context).sum do |item| Utils.to_number(item) end + + result.is_a?(BigDecimal) ? result.to_f : result end private diff --git a/test/integration/standard_filter_test.rb b/test/integration/standard_filter_test.rb index b2405f7f8..e945ad253 100644 --- a/test/integration/standard_filter_test.rb +++ b/test/integration/standard_filter_test.rb @@ -994,6 +994,42 @@ def test_sum_with_property_calls_to_liquid_on_property_values assert(t.foo > 0) end + def test_sum_of_floats + input = [0.1, 0.2, 0.3] + assert_equal(0.6, @filters.sum(input)) + assert_template_result("0.6", "{{ input | sum }}", { "input" => input }) + end + + def test_sum_of_negative_floats + input = [0.1, 0.2, -0.3] + assert_equal(0.0, @filters.sum(input)) + assert_template_result("0.0", "{{ input | sum }}", { "input" => input }) + end + + def test_sum_with_float_strings + input = [0.1, "0.2", "0.3"] + assert_equal(0.6, @filters.sum(input)) + assert_template_result("0.6", "{{ input | sum }}", { "input" => input }) + end + + def test_sum_resulting_in_negative_float + input = [0.1, -0.2, -0.3] + assert_equal(-0.4, @filters.sum(input)) + assert_template_result("-0.4", "{{ input | sum }}", { "input" => input }) + end + + def test_sum_with_floats_and_indexable_map_values + input = [{ "quantity" => 1 }, { "quantity" => 0.2, "weight" => -0.3 }, { "weight" => 0.4 }] + assert_equal(0.0, @filters.sum(input)) + assert_equal(1.2, @filters.sum(input, "quantity")) + assert_equal(0.1, @filters.sum(input, "weight")) + assert_equal(0.0, @filters.sum(input, "subtotal")) + assert_template_result("0", "{{ input | sum }}", { "input" => input }) + assert_template_result("1.2", "{{ input | sum: 'quantity' }}", { "input" => input }) + assert_template_result("0.1", "{{ input | sum: 'weight' }}", { "input" => input }) + assert_template_result("0", "{{ input | sum: 'subtotal' }}", { "input" => input }) + end + private def with_timezone(tz)