Add tests for failure modes for keys and intersect.

This commit is contained in:
Michael Kelly 2017-06-22 18:00:16 -07:00
Родитель 3e5759f9aa
Коммит 5d54fbc44c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 972176E09570E68A
3 изменённых файлов: 63 добавлений и 7 удалений

Просмотреть файл

@ -279,7 +279,8 @@ 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.
``list2``. Values are compared using strict equality. If ``list1`` or
``list2`` are not arrays, the returned value is ``undefined``.
:param list1:
The array to the left of the operator.
@ -383,7 +384,8 @@ function is the value being transformed.
.. js:function:: keys(obj)
Return an array of the given object's own keys (specifically, its enumerable
properties). Equivalent to `Object.keys`_.
properties). Similar to `Object.keys`_, except that if given a non-object,
``keys`` will return ``undefined``.
:param obj:
Object to get the keys for.

Просмотреть файл

@ -46,20 +46,29 @@ this.FilterExpressions = {
/**
* Return an array of the given object's own keys (specifically, its enumerable
* properties).
* properties), or undefined if the argument isn't an object.
* @param {Object} obj
* @return {Array[String]}
* @return {Array[String]|undefined}
*/
function keys(obj) {
if (typeof obj !== "object" || obj === null) {
return undefined;
}
return Object.keys(obj);
}
/**
* Find all the values that are present in both lists.
* Find all the values that are present in both lists. Returns undefined if
* the arguments are not both Arrays.
* @param {Array} listA
* @param {Array} listB
* @return {Array}
* @return {Array|undefined}
*/
function operatorIntersect(listA, listB) {
if (!Array.isArray(listA) || !Array.isArray(listB)) {
return undefined;
}
return listA.filter(item => listB.includes(item));
}

Просмотреть файл

@ -105,7 +105,7 @@ add_task(async function testKeys() {
);
// Test an object in the context
const context = {ctxObject: {baz: "string", biff: NaN}};
let context = {ctxObject: {baz: "string", biff: NaN}};
val = await FilterExpressions.eval("ctxObject|keys", context);
Assert.deepEqual(
@ -113,6 +113,34 @@ add_task(async function testKeys() {
new Set(["baz", "biff"]),
"keys returns the keys from an object in the context",
);
// Test that values from the prototype are not included
context = {ctxObject: Object.create({fooProto: 7})};
context.ctxObject.baz = 8;
context.ctxObject.biff = 5;
is(
await FilterExpressions.eval("ctxObject.fooProto", context),
7,
"Prototype properties are accessible via property access",
);
val = await FilterExpressions.eval("ctxObject|keys", context);
Assert.deepEqual(
new Set(val),
new Set(["baz", "biff"]),
"keys does not return properties from the object's prototype chain",
);
// Return undefined for non-objects
is(
await FilterExpressions.eval("ctxObject|keys", {ctxObject: 45}),
undefined,
"keys returns undefined for numbers",
);
is(
await FilterExpressions.eval("ctxObject|keys", {ctxObject: null}),
undefined,
"keys returns undefined for null",
);
});
// intersect tests
@ -140,4 +168,21 @@ add_task(async function testIntersect() {
new Set(["string"]),
"intersect can compare strings",
);
// Return undefined when intersecting things that aren't lists.
is(
await FilterExpressions.eval("5 intersect 7"),
undefined,
"intersect returns undefined for numbers",
);
is(
await FilterExpressions.eval("val intersect other", {val: null, other: null}),
undefined,
"intersect returns undefined for null",
);
is(
await FilterExpressions.eval("5 intersect [1, 2, 5]"),
undefined,
"intersect returns undefined if only one operand is a list",
);
});