spec/calculator_spec.rb in dentaku-3.4.2 vs spec/calculator_spec.rb in dentaku-3.5.0
- old
+ new
@@ -1,9 +1,10 @@
require 'spec_helper'
require 'dentaku'
describe Dentaku::Calculator do
let(:calculator) { described_class.new }
+ let(:with_case_sensitivity) { described_class.new(case_sensitive: true) }
let(:with_memory) { described_class.new.store(apples: 3) }
let(:with_aliases) { described_class.new(aliases: { round: ['rrround'] }) }
let(:without_nested_data) { described_class.new(nested_data_support: false) }
it 'evaluates an expression' do
@@ -184,10 +185,15 @@
end
it "finds no dependencies in array literals" do
expect(calculator.dependencies([1, 2, 3])).to eq([])
end
+
+ it "finds dependencies in item expressions" do
+ expect(calculator.dependencies('MAP(vals, val, val + step)')).to eq(['vals', 'step'])
+ expect(calculator.dependencies('ALL(people, person, person.age < adult)')).to eq(['people', 'adult'])
+ end
end
describe 'solve!' do
it "evaluates properly with variables, even if some in memory" do
expect(with_memory.solve!(
@@ -255,14 +261,19 @@
end
end
describe 'solve' do
it "returns :undefined when variables are unbound" do
- expressions = {more_apples: "apples + 1"}
- expect(calculator.solve(expressions)).to eq(more_apples: :undefined)
+ expressions = {more_apples: "apples + 1", compare_apples: "apples > 1"}
+ expect(calculator.solve(expressions)).to eq(more_apples: :undefined, compare_apples: :undefined)
end
+ it "returns :undefined when variables are nil" do
+ expressions = {more_apples: "apples + 1", compare_apples: "apples > 1"}
+ expect(calculator.store(apples: nil).solve(expressions)).to eq(more_apples: :undefined, compare_apples: :undefined)
+ end
+
it "allows passing in a custom value to an error handler" do
expressions = {more_apples: "apples + 1"}
expect(calculator.solve(expressions) { :foo })
.to eq(more_apples: :foo)
end
@@ -302,10 +313,24 @@
make_money: :undefined,
have_money: :undefined
)
}.not_to raise_error
end
+
+ it "integrates with custom functions" do
+ calculator.add_function(:custom, :integer, -> { 1 })
+
+ result = calculator.solve(
+ a: "1",
+ b: "CUSTOM() - a"
+ )
+
+ expect(result).to eq(
+ a: 1,
+ b: 0
+ )
+ end
end
it 'evaluates a statement with no variables' do
expect(calculator.evaluate('5+3')).to eq(8)
expect(calculator.evaluate('(1+1+1)/3*100')).to eq(100)
@@ -664,10 +689,35 @@
quantity: 10,
fruit: 'banana')
expect(value).to eq(5)
end
+ it 'handles nested case statements with case-sensitivity' do
+ formula = <<-FORMULA
+ CASE fruit
+ WHEN 'apple'
+ THEN 1 * quantity
+ WHEN 'banana'
+ THEN
+ CASE QUANTITY
+ WHEN 1 THEN 2
+ WHEN 10 THEN
+ CASE type
+ WHEN 'organic' THEN 5
+ END
+ END
+ END
+ FORMULA
+ value = with_case_sensitivity.evaluate(
+ formula,
+ type: 'organic',
+ quantity: 1,
+ QUANTITY: 10,
+ fruit: 'banana')
+ expect(value).to eq(5)
+ end
+
it 'handles multiple nested case statements' do
formula = <<-FORMULA
CASE fruit
WHEN 'apple'
THEN
@@ -707,9 +757,15 @@
unless [:atanh, :frexp, :lgamma].include?(method)
expect(calculator.evaluate("#{method}(1) + 1")).to be_within(0.00001).of(Math.send(method, 1) + 1)
end
end
end
+ end
+
+ it 'are defined with a properly named class that represents it to support AST marshaling' do
+ expect {
+ Marshal.dump(calculator.ast('SQRT(20)'))
+ }.not_to raise_error
end
end
describe 'disable_cache' do
before do