Skip to content

Commit a607621

Browse files
committed
Implement comments
1 parent d29cc0f commit a607621

File tree

1 file changed

+179
-191
lines changed

1 file changed

+179
-191
lines changed
Lines changed: 179 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
/****************************************************************************
2-
* Copyright 2018, 2020-2021, Optimizely, Inc. and contributors *
3-
* *
4-
* Licensed under the Apache License, Version 2.0 (the "License"); *
5-
* you may not use this file except in compliance with the License. *
6-
* You may obtain a copy of the License at *
7-
* *
8-
* http://www.apache.org/licenses/LICENSE-2.0 *
9-
* *
10-
* Unless required by applicable law or agreed to in writing, software *
11-
* distributed under the License is distributed on an "AS IS" BASIS, *
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13-
* See the License for the specific language governing permissions and *
14-
* limitations under the License. *
15-
***************************************************************************/
1+
/**
2+
* Copyright 2025, Optimizely
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
1616
import { describe, it, vi, expect } from 'vitest';
1717

1818
import * as conditionTreeEvaluator from '.';
@@ -33,198 +33,186 @@ const conditionC = {
3333
type: 'custom_attribute',
3434
value: 'CA',
3535
};
36+
describe('evaluate', function() {
37+
it('should return true for a leaf condition when the leaf condition evaluator returns true', function() {
38+
expect(
39+
conditionTreeEvaluator.evaluate(conditionA, function() {
40+
return true;
41+
})
42+
).toBe(true);
43+
});
44+
45+
it('should return false for a leaf condition when the leaf condition evaluator returns false', function() {
46+
expect(
47+
conditionTreeEvaluator.evaluate(conditionA, function() {
48+
return false;
49+
})
50+
).toBe(false);
51+
});
3652

37-
describe('lib/core/condition_tree_evaluator', function() {
38-
describe('APIs', function() {
39-
describe('evaluate', function() {
40-
it('should return true for a leaf condition when the leaf condition evaluator returns true', function() {
53+
describe('and evaluation', function() {
54+
it('should return true when ALL conditions evaluate to true', function() {
55+
expect(
56+
conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], function() {
57+
return true;
58+
})
59+
).toBe(true);
60+
});
61+
62+
it('should return false if one condition evaluates to false', function() {
63+
const leafEvaluator = vi.fn();
64+
leafEvaluator.mockImplementationOnce(() => true).mockImplementationOnce(() => false);
65+
expect(conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], leafEvaluator)).toBe(false);
66+
});
67+
68+
describe('null handling', function() {
69+
it('should return null when all operands evaluate to null', function() {
4170
expect(
42-
conditionTreeEvaluator.evaluate(conditionA, function() {
43-
return true;
71+
conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], function() {
72+
return null;
4473
})
45-
).toBe(true);
74+
).toBeNull();
75+
});
76+
77+
it('should return null when operands evaluate to trues and nulls', function() {
78+
const leafEvaluator = vi.fn();
79+
leafEvaluator.mockImplementationOnce(() => true).mockImplementationOnce(() => null);
80+
expect(conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], leafEvaluator)).toBeNull();
4681
});
4782

48-
it('should return false for a leaf condition when the leaf condition evaluator returns false', function() {
83+
it('should return false when operands evaluate to falses and nulls', function() {
84+
const leafEvaluator = vi.fn();
85+
leafEvaluator.mockImplementationOnce(() => false).mockImplementationOnce(() => null);
86+
expect(conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], leafEvaluator)).toBe(false);
87+
88+
leafEvaluator.mockReset();
89+
leafEvaluator.mockImplementationOnce(() => null).mockImplementationOnce(() => false);
90+
expect(conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], leafEvaluator)).toBe(false);
91+
});
92+
93+
it('should return false when operands evaluate to trues, falses, and nulls', function() {
94+
const leafEvaluator = vi.fn();
95+
leafEvaluator
96+
.mockImplementationOnce(() => true)
97+
.mockImplementationOnce(() => false)
98+
.mockImplementationOnce(() => null);
99+
expect(conditionTreeEvaluator.evaluate(['and', conditionA, conditionB, conditionC], leafEvaluator)).toBe(false);
100+
});
101+
});
102+
});
103+
104+
describe('or evaluation', function() {
105+
it('should return true if any condition evaluates to true', function() {
106+
const leafEvaluator = vi.fn();
107+
leafEvaluator.mockImplementationOnce(() => false).mockImplementationOnce(() => true);
108+
expect(conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], leafEvaluator)).toBe(true);
109+
});
110+
111+
it('should return false if all conditions evaluate to false', function() {
112+
expect(
113+
conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], function() {
114+
return false;
115+
})
116+
).toBe(false);
117+
});
118+
119+
describe('null handling', function() {
120+
it('should return null when all operands evaluate to null', function() {
49121
expect(
50-
conditionTreeEvaluator.evaluate(conditionA, function() {
51-
return false;
122+
conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], function() {
123+
return null;
52124
})
53-
).toBe(false)
125+
).toBeNull();
54126
});
55127

56-
describe('and evaluation', function() {
57-
it('should return true when ALL conditions evaluate to true', function() {
58-
expect(
59-
conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], function() {
60-
return true;
61-
})
62-
).toBe(true);
63-
});
64-
65-
it('should return false if one condition evaluates to false', function() {
66-
const leafEvaluator = vi.fn();
67-
leafEvaluator.mockImplementationOnce(() => true)
68-
.mockImplementationOnce(() => false);
69-
expect(conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], leafEvaluator)).toBe(false);
70-
});
71-
72-
describe('null handling', function() {
73-
it('should return null when all operands evaluate to null', function() {
74-
expect(
75-
conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], function() {
76-
return null;
77-
})
78-
).toBeNull();
79-
});
80-
81-
it('should return null when operands evaluate to trues and nulls', function() {
82-
const leafEvaluator = vi.fn();
83-
leafEvaluator.mockImplementationOnce(() => true)
84-
.mockImplementationOnce(() => null);
85-
expect(conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], leafEvaluator)).toBeNull();
86-
});
87-
88-
it('should return false when operands evaluate to falses and nulls', function() {
89-
const leafEvaluator = vi.fn();
90-
leafEvaluator.mockImplementationOnce(() => false)
91-
.mockImplementationOnce(() => null);
92-
expect(conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], leafEvaluator)).toBe(false);
93-
94-
leafEvaluator.mockReset();
95-
leafEvaluator.mockImplementationOnce(() => null)
96-
.mockImplementationOnce(() => false);
97-
expect(conditionTreeEvaluator.evaluate(['and', conditionA, conditionB], leafEvaluator)).toBe(false);
98-
});
99-
100-
it('should return false when operands evaluate to trues, falses, and nulls', function() {
101-
const leafEvaluator = vi.fn();
102-
leafEvaluator.mockImplementationOnce(() => true)
103-
.mockImplementationOnce(() => false)
104-
.mockImplementationOnce(() => null);
105-
expect(conditionTreeEvaluator.evaluate(['and', conditionA, conditionB, conditionC], leafEvaluator)).toBe(false);
106-
});
107-
});
128+
it('should return true when operands evaluate to trues and nulls', function() {
129+
const leafEvaluator = vi.fn();
130+
leafEvaluator.mockImplementationOnce(() => true).mockImplementationOnce(() => null);
131+
expect(conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], leafEvaluator)).toBe(true);
108132
});
109133

110-
describe('or evaluation', function() {
111-
it('should return true if any condition evaluates to true', function() {
112-
const leafEvaluator = vi.fn();
113-
leafEvaluator.mockImplementationOnce(() => false)
114-
.mockImplementationOnce(() => true);
115-
expect(conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], leafEvaluator)).toBe(true);
116-
});
117-
118-
it('should return false if all conditions evaluate to false', function() {
119-
expect(
120-
conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], function() {
121-
return false;
122-
})
123-
).toBe(false);
124-
});
125-
126-
describe('null handling', function() {
127-
it('should return null when all operands evaluate to null', function() {
128-
expect(
129-
conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], function() {
130-
return null;
131-
})
132-
).toBeNull();
133-
});
134-
135-
it('should return true when operands evaluate to trues and nulls', function() {
136-
const leafEvaluator = vi.fn();
137-
leafEvaluator.mockImplementationOnce(() => true)
138-
.mockImplementationOnce(() => null);
139-
expect(conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], leafEvaluator)).toBe(true);
140-
});
141-
142-
it('should return null when operands evaluate to falses and nulls', function() {
143-
const leafEvaluator = vi.fn();
144-
leafEvaluator.mockImplementationOnce(() => null)
145-
.mockImplementationOnce(() => false);
146-
expect(conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], leafEvaluator)).toBeNull();
147-
148-
leafEvaluator.mockReset();
149-
leafEvaluator.mockImplementationOnce(() => false)
150-
.mockImplementationOnce(() => null);
151-
expect(conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], leafEvaluator)).toBeNull();
152-
});
153-
154-
it('should return true when operands evaluate to trues, falses, and nulls', function() {
155-
const leafEvaluator = vi.fn();
156-
leafEvaluator.mockImplementationOnce(() => true)
157-
.mockImplementationOnce(() => null)
158-
.mockImplementationOnce(() => false);
159-
expect(conditionTreeEvaluator.evaluate(['or', conditionA, conditionB, conditionC], leafEvaluator)).toBe(true);
160-
});
161-
});
134+
it('should return null when operands evaluate to falses and nulls', function() {
135+
const leafEvaluator = vi.fn();
136+
leafEvaluator.mockImplementationOnce(() => null).mockImplementationOnce(() => false);
137+
expect(conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], leafEvaluator)).toBeNull();
138+
139+
leafEvaluator.mockReset();
140+
leafEvaluator.mockImplementationOnce(() => false).mockImplementationOnce(() => null);
141+
expect(conditionTreeEvaluator.evaluate(['or', conditionA, conditionB], leafEvaluator)).toBeNull();
162142
});
163143

164-
describe('not evaluation', function() {
165-
it('should return true if the condition evaluates to false', function() {
166-
expect(
167-
conditionTreeEvaluator.evaluate(['not', conditionA], function() {
168-
return false;
169-
})
170-
).toBe(true);
171-
});
172-
173-
it('should return false if the condition evaluates to true', function() {
174-
expect(
175-
conditionTreeEvaluator.evaluate(['not', conditionB], function() {
176-
return true;
177-
})
178-
).toBe(false);
179-
});
180-
181-
it('should return the result of negating the first condition, and ignore any additional conditions', function() {
182-
let result = conditionTreeEvaluator.evaluate(['not', '1', '2', '1'], function(id) {
183-
return String(id) === '1';
184-
});
185-
expect(result).toBe(false);
186-
result = conditionTreeEvaluator.evaluate(['not', '1', '2', '1'], function(id) {
187-
return String(id) === '2';
188-
});
189-
expect(result).toBe(true);
190-
result = conditionTreeEvaluator.evaluate(['not', '1', '2', '3'], function(id) {
191-
return String(id) === '1' ? null : String(id) === '3';
192-
});
193-
expect(result).toBeNull();
194-
});
195-
196-
describe('null handling', function() {
197-
it('should return null when operand evaluates to null', function() {
198-
expect(
199-
conditionTreeEvaluator.evaluate(['not', conditionA], function() {
200-
return null;
201-
})
202-
).toBeNull();
203-
});
204-
205-
it('should return null when there are no operands', function() {
206-
expect(
207-
conditionTreeEvaluator.evaluate(['not'], function() {
208-
return null;
209-
})
210-
).toBeNull();
211-
});
212-
});
144+
it('should return true when operands evaluate to trues, falses, and nulls', function() {
145+
const leafEvaluator = vi.fn();
146+
leafEvaluator
147+
.mockImplementationOnce(() => true)
148+
.mockImplementationOnce(() => null)
149+
.mockImplementationOnce(() => false);
150+
expect(conditionTreeEvaluator.evaluate(['or', conditionA, conditionB, conditionC], leafEvaluator)).toBe(true);
151+
});
152+
});
153+
});
154+
155+
describe('not evaluation', function() {
156+
it('should return true if the condition evaluates to false', function() {
157+
expect(
158+
conditionTreeEvaluator.evaluate(['not', conditionA], function() {
159+
return false;
160+
})
161+
).toBe(true);
162+
});
163+
164+
it('should return false if the condition evaluates to true', function() {
165+
expect(
166+
conditionTreeEvaluator.evaluate(['not', conditionB], function() {
167+
return true;
168+
})
169+
).toBe(false);
170+
});
171+
172+
it('should return the result of negating the first condition, and ignore any additional conditions', function() {
173+
let result = conditionTreeEvaluator.evaluate(['not', '1', '2', '1'], function(id: string) {
174+
return id === '1';
175+
});
176+
expect(result).toBe(false);
177+
result = conditionTreeEvaluator.evaluate(['not', '1', '2', '1'], function(id: string) {
178+
return id === '2';
179+
});
180+
expect(result).toBe(true);
181+
result = conditionTreeEvaluator.evaluate(['not', '1', '2', '3'], function(id: string) {
182+
return id === '1' ? null : id === '3';
183+
});
184+
expect(result).toBeNull();
185+
});
186+
187+
describe('null handling', function() {
188+
it('should return null when operand evaluates to null', function() {
189+
expect(
190+
conditionTreeEvaluator.evaluate(['not', conditionA], function() {
191+
return null;
192+
})
193+
).toBeNull();
213194
});
214195

215-
describe('implicit operator', function() {
216-
it('should behave like an "or" operator when the first item in the array is not a recognized operator', function() {
217-
const leafEvaluator = vi.fn();
218-
leafEvaluator.mockImplementationOnce(() => true)
219-
.mockImplementationOnce(() => false);
220-
expect(conditionTreeEvaluator.evaluate([conditionA, conditionB], leafEvaluator)).toBe(true);
221-
expect(
222-
conditionTreeEvaluator.evaluate([conditionA, conditionB], function() {
223-
return false;
224-
})
225-
).toBe(false);
226-
});
196+
it('should return null when there are no operands', function() {
197+
expect(
198+
conditionTreeEvaluator.evaluate(['not'], function() {
199+
return null;
200+
})
201+
).toBeNull();
227202
});
228203
});
229204
});
205+
206+
describe('implicit operator', function() {
207+
it('should behave like an "or" operator when the first item in the array is not a recognized operator', function() {
208+
const leafEvaluator = vi.fn();
209+
leafEvaluator.mockImplementationOnce(() => true).mockImplementationOnce(() => false);
210+
expect(conditionTreeEvaluator.evaluate([conditionA, conditionB], leafEvaluator)).toBe(true);
211+
expect(
212+
conditionTreeEvaluator.evaluate([conditionA, conditionB], function() {
213+
return false;
214+
})
215+
).toBe(false);
216+
});
217+
});
230218
});

0 commit comments

Comments
 (0)