Jest Condition Evaluator
This challenge involves implementing a system to evaluate complex conditions within your Jest tests. This is crucial for creating highly specific and dynamic test assertions, allowing you to verify that certain states or behaviors are met under precise circumstances, making your tests more robust and expressive.
Problem Description
You need to create a function, evaluateConditions, that takes an object representing the current state and an array of conditions to evaluate against that state. Each condition is an object with a field (the key in the state object), an operator (a string representing a comparison), and a value (the value to compare against).
The function should return true if all conditions are met, and false otherwise.
Key Requirements:
-
Support for multiple operators: Implement support for at least the following operators:
==(loose equality)===(strict equality)!=(loose inequality)!==(strict inequality)>(greater than)<(less than)>=(greater than or equal to)<=(less than or equal to)includes(checks if a string or array contains a value)startsWith(checks if a string starts with a given prefix)endsWith(checks if a string ends with a given suffix)
-
Handling missing fields: If a
fieldspecified in aconditiondoes not exist in thestateobject, the condition should be considered unmet, returningfalsefor that specific condition. -
All conditions must pass: The function should return
trueonly if all provided conditions evaluate totrue. If even one condition fails, the function should returnfalse. -
Type Safety: The solution should be implemented in TypeScript, ensuring type safety for state and conditions.
Expected Behavior:
- If the
stateobject is empty andconditionsis empty, returntrue. - If
conditionsis empty, returntrueregardless of thestate. - If any condition fails due to a missing field or an unmet comparison, the function returns
false. - If all conditions are met, the function returns
true.
Edge Cases to Consider:
- Comparing different data types (e.g., number with string).
nullandundefinedvalues in the state.- Empty strings, arrays, or objects in the state.
- Conditions involving
nullorundefinedas thevalue.
Examples
Example 1:
const state = {
user: {
name: "Alice",
age: 30,
roles: ["admin", "editor"]
},
isActive: true
};
const conditions = [
{ field: "user.name", operator: "===", value: "Alice" },
{ field: "user.age", operator: ">", value: 25 },
{ field: "isActive", operator: "===", value: true }
];
// Expected Output: true
// Explanation: All conditions match the state. "Alice" === "Alice", 30 > 25, and true === true.
Example 2:
const state = {
product: {
name: "Gadget",
price: 99.99
},
stock: 5
};
const conditions = [
{ field: "product.name", operator: "startsWith", value: "Gad" },
{ field: "product.price", operator: "<", value: 100 },
{ field: "stock", operator: "===", value: 10 }
];
// Expected Output: false
// Explanation: The condition `stock === 10` fails because the stock is 5.
Example 3:
const state = {
orderId: "ORD12345",
items: ["book", "pen"]
};
const conditions = [
{ field: "orderId", operator: "includes", value: "123" },
{ field: "items", operator: "includes", value: "pencil" }
];
// Expected Output: false
// Explanation: The condition `items includes "pencil"` fails because the items array does not contain "pencil".
Example 4 (Missing Field):
const state = {
userData: {
email: "test@example.com"
}
};
const conditions = [
{ field: "userData.email", operator: "===", value: "test@example.com" },
{ field: "userData.phone", operator: "!==", value: null } // 'phone' field is missing
];
// Expected Output: false
// Explanation: The condition `userData.phone !== null` fails because the 'phone' field does not exist in the state.
Constraints
- The
stateobject can be arbitrarily nested. - The
conditionsarray can contain up to 100 conditions. - The
fieldpath in conditions will use dot notation for nesting (e.g.,user.address.city). - The
valuein conditions can be of any primitive type or an array. - The
operatorstring will always be one of the supported operators.
Notes
- For nested fields like
user.age, you'll need a way to safely access them. Consider using a helper function for deep property access. - The
includesoperator should work for both strings and arrays. - Pay close attention to type coercion when implementing loose equality (
==) and inequality (!=). - The
startsWithandendsWithoperators should only be applied to string values. If the field is not a string, these conditions should fail.