spec/calculator_spec.rb in dentaku-2.0.10 vs spec/calculator_spec.rb in dentaku-2.0.11
- old
+ new
@@ -30,10 +30,13 @@
expect(calculator.evaluate('15 % 8')).to eq(7)
expect(calculator.evaluate('(((695759/735000)^(1/(1981-1991)))-1)*1000').round(4)).to eq(5.5018)
expect(calculator.evaluate('0.253/0.253')).to eq(1)
expect(calculator.evaluate('0.253/d', d: 0.253)).to eq(1)
expect(calculator.evaluate('10 + x', x: 'abc')).to be_nil
+ expect(calculator.evaluate('t + 1*24*60*60', t: Time.local(2017, 1, 1))).to eq(Time.local(2017, 1, 2))
+ expect(calculator.evaluate("2 | 3 * 9")).to eq (27)
+ expect(calculator.evaluate("2 & 3 * 9")).to eq (2)
end
describe 'memory' do
it { expect(calculator).to be_empty }
it { expect(with_memory).not_to be_empty }
@@ -57,10 +60,16 @@
it 'stores formulas' do
calculator.store_formula('area', 'length * width')
expect(calculator.evaluate!('area', length: 5, width: 5)).to eq 25
end
+
+ it 'stores nested hashes' do
+ calculator.store({a: {basket: {of: 'apples'}}, b: 2})
+ expect(calculator.evaluate!('a.basket.of')).to eq 'apples'
+ expect(calculator.evaluate!('b')).to eq 2
+ end
end
describe 'dependencies' do
it "finds dependencies in a generic statement" do
expect(calculator.dependencies("bob + dole / 3")).to eq(['bob', 'dole'])
@@ -167,10 +176,18 @@
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)
end
+ it 'evaluates negation' do
+ expect(calculator.evaluate('-negative', negative: -1)).to eq(1)
+ expect(calculator.evaluate('-negative', negative: '-1')).to eq(1)
+ expect(calculator.evaluate('-negative - 1', negative: '-1')).to eq(0)
+ expect(calculator.evaluate('-negative - 1', negative: '1')).to eq(-2)
+ expect(calculator.evaluate('-(negative) - 1', negative: '1')).to eq(-2)
+ end
+
it 'fails to evaluate unbound statements' do
unbound = 'foo * 1.5'
expect { calculator.evaluate!(unbound) }.to raise_error(Dentaku::UnboundVariableError)
expect { calculator.evaluate!(unbound) }.to raise_error do |error|
expect(error.unbound_variables).to eq ['foo']
@@ -178,10 +195,15 @@
expect(calculator.evaluate(unbound)).to be_nil
expect(calculator.evaluate(unbound) { :bar }).to eq :bar
expect(calculator.evaluate(unbound) { |e| e }).to eq unbound
end
+ it 'fails to evaluate incomplete statements' do
+ incomplete = 'true AND'
+ expect { calculator.evaluate!(incomplete) }.to raise_error(Dentaku::ParseError)
+ end
+
it 'evaluates unbound statements given a binding in memory' do
expect(calculator.evaluate('foo * 1.5', foo: 2)).to eq(3)
expect(calculator.bind(monkeys: 3).evaluate('monkeys < 7')).to be_truthy
expect(calculator.evaluate('monkeys / 1.5')).to eq(2)
end
@@ -221,10 +243,24 @@
expect(calculator.evaluate('some_boolean OR 7 > 5', some_boolean: true)).to be_truthy
expect(calculator.evaluate('some_boolean OR 7 < 5', some_boolean: true)).to be_truthy
expect(calculator.evaluate('some_boolean OR 7 < 5', some_boolean: false)).to be_falsey
end
+ it 'compares Time variables' do
+ expect(calculator.evaluate('t1 < t2', t1: Time.local(2017, 1, 1).to_datetime, t2: Time.local(2017, 1, 2).to_datetime)).to be_truthy
+ expect(calculator.evaluate('t1 < t2', t1: Time.local(2017, 1, 2).to_datetime, t2: Time.local(2017, 1, 1).to_datetime)).to be_falsy
+ expect(calculator.evaluate('t1 > t2', t1: Time.local(2017, 1, 1).to_datetime, t2: Time.local(2017, 1, 2).to_datetime)).to be_falsy
+ expect(calculator.evaluate('t1 > t2', t1: Time.local(2017, 1, 2).to_datetime, t2: Time.local(2017, 1, 1).to_datetime)).to be_truthy
+ end
+
+ it 'compares Time literals with Time variables' do
+ expect(calculator.evaluate('t1 < 2017-01-02', t1: Time.local(2017, 1, 1).to_datetime)).to be_truthy
+ expect(calculator.evaluate('t1 < 2017-01-02', t1: Time.local(2017, 1, 3).to_datetime)).to be_falsy
+ expect(calculator.evaluate('t1 > 2017-01-02', t1: Time.local(2017, 1, 1).to_datetime)).to be_falsy
+ expect(calculator.evaluate('t1 > 2017-01-02', t1: Time.local(2017, 1, 3).to_datetime)).to be_truthy
+ end
+
describe 'functions' do
it 'include IF' do
expect(calculator.evaluate('if(foo < 8, 10, 20)', foo: 2)).to eq(10)
expect(calculator.evaluate('if(foo < 8, 10, 20)', foo: 9)).to eq(20)
expect(calculator.evaluate('if (foo < 8, 10, 20)', foo: 2)).to eq(10)
@@ -279,20 +315,20 @@
expect(calculator.evaluate('rounddown(1.234, 2)')).to eq(1.23)
end
end
end
- describe 'explicit NULL' do
- it 'can be used in IF statements' do
+ describe 'nil values' do
+ it 'can be used explicitly' do
expect(calculator.evaluate('IF(null, 1, 2)')).to eq(2)
end
- it 'can be used in IF statements when passed in' do
+ it 'can be assigned to a variable' do
expect(calculator.evaluate('IF(foo, 1, 2)', foo: nil)).to eq(2)
end
- it 'nil values are carried across middle terms' do
+ it 'are carried across middle terms' do
results = calculator.solve!(
choice: 'IF(bar, 1, 2)',
bar: 'foo',
foo: nil)
expect(results).to eq(
@@ -300,11 +336,11 @@
bar: nil,
foo: nil
)
end
- it 'raises errors when used in arithmetic operation' do
+ it 'raise errors when used in arithmetic operations' do
expect {
calculator.solve!(more_apples: "apples + 1", apples: nil)
}.to raise_error(Dentaku::ArgumentError)
end
end
@@ -473,12 +509,12 @@
expect(calculator.ast_cache.keys.sort).to eq(['1+1'])
end
end
describe 'string functions' do
- it 'concatenates two strings' do
+ it 'concatenates strings' do
expect(
- calculator.evaluate('CONCAT(s1, s2)', 's1' => 'abc', 's2' => 'def')
+ calculator.evaluate('CONCAT(s1, s2, s3)', 's1' => 'ab', 's2' => 'cd', 's3' => 'ef')
).to eq 'abcdef'
end
end
end