Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding dotNotation property and test #48

Merged
merged 6 commits into from
Apr 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions src/prop_tests/dotNotation_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
var QUnit = require("steal-qunit");

var set = require('../set-core'),
props = require("../props");

QUnit.module("can-set props.dotNotation");

/*
* For the dotNotation prop, we define sets like so:
*
* For a property 'n.p', with value 'IL'
* x ∈ X | x.n.p = 'IL'
*
*/
test('dotNotation set membership', function() {
/*
* For a property 'n.p', with value 'IL'
* x ∈ X | x.n.p == 'IL'
*/
var prop = props.dotNotation('n.p'),
alg = new set.Algebra(prop),
res = alg.has({'n.p': 'IL'}, {n:{p:'IL'}});
ok(res, "object with nested property is member of set using dotNotation");

/*
* For a property 'n.p', with value 'IL'
* x ∉ X | x.n.p != 'IL'
*/
res = alg.has({'n.p': 'IL'}, {n:{p:'MI'}});
ok(res === false, "object with nested property not a member of set using dotNotation");

/*
* For a property 'n.p.s', with value 'IL'
* x ∈ X | x.n.p.s == 'IL'
*/
prop = props.dotNotation('n.p.s');
alg = new set.Algebra(prop);
res = alg.has({'n.p.s': 'IL'}, {n:{p:{s:'IL'}}});
ok(res, "object with deep nested property is member of set using dotNotation");
});

test('dotNotation set equality', function() {
var prop = props.dotNotation('n.p'),
alg = new set.Algebra(prop),
set1 = {'n.p': 'IL'},
set2 = {'n.p': 'IL'},
set3 = {'n.p': 'MI'},
set4 = {n:{p:'MI'}};

/*
* {x | x ∈ X, x.n.p == 'IL'} = {y | y ∈ Y, y.n.p == 'IL'}
*/
ok(alg.equal(set1, set2) && alg.equal(set2, set1), "sets with dotNotation properties are equivalent");

/*
* {x | x ∈ X, x.n.p == 'IL'} != {y | y ∈ Y, y.n.p == 'MI'}
*/
ok(alg.equal(set1, set3) === false, "sets with dotNotation properties are not equivalent");

/*
* {x | x ∈ X, x.n.p == 'MI'} = {y | y ∈ Y, y.n.p == 'MI'}
*/
ok(alg.equal(set4, set3) === false, "sets with dotNotation properties are equivalent to sets with nested properties");
});

test('dotNotation set subset', function() {
var alg = new set.Algebra(
props.dotNotation('address.state'),
props.dotNotation('address.city')
),
set1 = {'address.state': 'IL'},
set2 = {'address.state': 'IL', 'address.city': 'Chicago'},
set3 = {address: {state: 'IL', city: 'Chicago'}};

/*
* {x | x ∈ X, x.address.state = 'IL', x.address.city = 'Chicago'} ⊆ {y | y ∈ Y, y.address.state == 'IL'}
*/
ok(alg.subset(set2, set1), "sets with dotNotation property is a subset of another dotNotation set");

/*
* {x | x ∈ X, x.address.state = 'IL', x.address.city = 'Chicago'} ⊆ {y | y ∈ Y, y.address.state == 'IL'}
*/
ok(alg.subset(set3, set1), "sets with nested property notation is a subset of a dotNotation set");

/*
* {y | y ∈ Y, y.address.state == 'IL'} ⊆ ξ
*/
ok(alg.subset(set1, {}), "sets with dotNotation properties are subsets of the universal set");

/*
* ξ ⊄ {y | y ∈ Y, y.address.state == 'IL'}
*/
ok(alg.subset({}, set1) === false, "the universal set is not a subset of a set with dotNotation");
});
47 changes: 47 additions & 0 deletions src/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -483,4 +483,51 @@ props.rangeInclusive = function(startIndexProperty, endIndexProperty){
});
};

var nestedLookup = function(obj, propNameArray) {
if (obj === undefined) {
return undefined;
}

if (propNameArray.length === 1) {
return obj[propNameArray[0]];
} else {
return nestedLookup(obj[propNameArray[0]], propNameArray.slice(1));
}
};
/**
* @function can-set.props.dotNotation dotNotation
* @parent can-set.props
*
* @description Supports MongoDB-style 'dot notation' properties.
*
* @signature `set.props.dotNotation(dotProperty)`
*
* Defines a property that specifies a MongoDB-style nested property match.
* For example, a set property of "address.city" matches against the value of the nested `{address: {city}}` value.
*
* ```
* set.props.dotNotation("address.city")
* ```
*
* @param {String} dotProperty The MongoDB-style nested property name
* @return {can-set.compares} Returns a comparator used to build a set algebra
*/
props.dotNotation = function(dotProperty){
var compares = new clause.Where({});

compares[dotProperty] = function(aVal, bVal, a, b, propertyName) {
// if the value wasn't picked out from the parent try a dotNotation lookup
if (aVal === undefined) {
aVal = nestedLookup(a, propertyName.split('.'));
}
if (bVal === undefined) {
bVal = nestedLookup(b, propertyName.split('.'));
}

return aVal === bVal;
};

return compares;
};

module.exports = props;
1 change: 1 addition & 0 deletions src/props_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ require('./prop_tests/rangeInclusive_test');
require('./prop_tests/offsetLimit_test');
require('./prop_tests/boolean_test');
require('./prop_tests/enum_test');
require('./prop_tests/dotNotation_test');