зеркало из https://github.com/mozilla/normandy.git
Fix #756: Add keys transform and intersection operator to filter expressions.
This commit is contained in:
Родитель
6d52f03e07
Коммит
3e5759f9aa
|
@ -270,6 +270,27 @@ filter expressions.
|
|||
object varies depending on the recipe, and use of this property is only
|
||||
recommended if you are familiar with the argument schema.
|
||||
|
||||
Operators
|
||||
---------
|
||||
This section describes the special operators available to filter expressions on
|
||||
top of the standard operators in JEXL. They're documented as functions, and the
|
||||
parameters correspond to the operands.
|
||||
|
||||
.. js:function:: intersect(list1, list2)
|
||||
|
||||
Returns an array of all values in ``list1`` that are also present in
|
||||
``list2``. Values are compared using strict equality.
|
||||
|
||||
:param list1:
|
||||
The array to the left of the operator.
|
||||
:param list2:
|
||||
The array to the right of the operator
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// Evaluates to [2, 3]
|
||||
[1, 2, 3, 4] intersect [5, 6, 2, 7, 3]
|
||||
|
||||
Transforms
|
||||
----------
|
||||
This section describes the transforms available to filter expressions, and what
|
||||
|
@ -359,6 +380,21 @@ function is the value being transformed.
|
|||
|
||||
.. _ISO 8601: https://www.w3.org/TR/NOTE-datetime
|
||||
|
||||
.. js:function:: keys(obj)
|
||||
|
||||
Return an array of the given object's own keys (specifically, its enumerable
|
||||
properties). Equivalent to `Object.keys`_.
|
||||
|
||||
:param obj:
|
||||
Object to get the keys for.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// Evaluates to ['foo', 'bar']
|
||||
{foo: 1, bar:2}|keys
|
||||
|
||||
.. _Object.keys: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
|
||||
|
||||
Preference Filters
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
.. js:function:: preferenceValue(prefKey, defaultValue)
|
||||
|
|
|
@ -31,7 +31,9 @@ XPCOMUtils.defineLazyGetter(this, "jexl", () => {
|
|||
preferenceValue: PreferenceFilters.preferenceValue,
|
||||
preferenceIsUserSet: PreferenceFilters.preferenceIsUserSet,
|
||||
preferenceExists: PreferenceFilters.preferenceExists,
|
||||
keys,
|
||||
});
|
||||
jexl.addBinaryOp("intersect", 40, operatorIntersect);
|
||||
return jexl;
|
||||
});
|
||||
|
||||
|
@ -41,3 +43,23 @@ this.FilterExpressions = {
|
|||
return jexl.eval(onelineExpr, context);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Return an array of the given object's own keys (specifically, its enumerable
|
||||
* properties).
|
||||
* @param {Object} obj
|
||||
* @return {Array[String]}
|
||||
*/
|
||||
function keys(obj) {
|
||||
return Object.keys(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the values that are present in both lists.
|
||||
* @param {Array} listA
|
||||
* @param {Array} listB
|
||||
* @return {Array}
|
||||
*/
|
||||
function operatorIntersect(listA, listB) {
|
||||
return listA.filter(item => listB.includes(item));
|
||||
}
|
||||
|
|
|
@ -91,3 +91,53 @@ add_task(async function() {
|
|||
val = await FilterExpressions.eval('"normandy.test.value"|preferenceExists == true');
|
||||
ok(val, "preferenceExists expression fails existence check appropriately");
|
||||
});
|
||||
|
||||
// keys tests
|
||||
add_task(async function testKeys() {
|
||||
let val;
|
||||
|
||||
// Test an object defined in JEXL
|
||||
val = await FilterExpressions.eval("{foo: 1, bar: 2}|keys");
|
||||
Assert.deepEqual(
|
||||
new Set(val),
|
||||
new Set(["foo", "bar"]),
|
||||
"keys returns the keys from an object in JEXL",
|
||||
);
|
||||
|
||||
// Test an object in the context
|
||||
const context = {ctxObject: {baz: "string", biff: NaN}};
|
||||
val = await FilterExpressions.eval("ctxObject|keys", context);
|
||||
|
||||
Assert.deepEqual(
|
||||
new Set(val),
|
||||
new Set(["baz", "biff"]),
|
||||
"keys returns the keys from an object in the context",
|
||||
);
|
||||
});
|
||||
|
||||
// intersect tests
|
||||
add_task(async function testIntersect() {
|
||||
let val;
|
||||
|
||||
val = await FilterExpressions.eval("[1, 2, 3] intersect [4, 2, 6, 7, 3]");
|
||||
Assert.deepEqual(
|
||||
new Set(val),
|
||||
new Set([2, 3]),
|
||||
"intersect finds the common elements between two lists in JEXL",
|
||||
);
|
||||
|
||||
const context = {left: [5, 7], right: [4, 5, 3]};
|
||||
val = await FilterExpressions.eval("left intersect right", context);
|
||||
Assert.deepEqual(
|
||||
new Set(val),
|
||||
new Set([5]),
|
||||
"intersect finds the common elements between two lists in the context",
|
||||
);
|
||||
|
||||
val = await FilterExpressions.eval("['string', 2] intersect [4, 'string', 'other', 3]");
|
||||
Assert.deepEqual(
|
||||
new Set(val),
|
||||
new Set(["string"]),
|
||||
"intersect can compare strings",
|
||||
);
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче