Skip to content
This repository has been archived by the owner on Feb 13, 2022. It is now read-only.

Commit

Permalink
Merge pull request #50 from praekelt/feature/issue-50-update-combinat…
Browse files Browse the repository at this point in the history
…ion-rule-to-handle-single-nested-block

Update Combination Rule to handle single nested block
  • Loading branch information
nathanbegbie committed Nov 21, 2017
2 parents 39fac7d + 480d2b5 commit 9ff3ce3
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 30 deletions.
4 changes: 3 additions & 1 deletion molo/surveys/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ def evaluate(list_):
Sample Input:
'''
if len(list_) == 3:
if len(list_) == 1 and isinstance(list_[0], list):
return evaluate(list_[0])
elif len(list_) == 3:
operator = list_[1]
first = list_[0] if isinstance(list_[0], bool) else evaluate(list_[0])
second = list_[2] if isinstance(list_[2], bool) else evaluate(list_[2])
Expand Down
35 changes: 22 additions & 13 deletions molo/surveys/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,26 +398,35 @@ def clean(self):
elif isinstance(self.body.stream_data[0], tuple):
newData = [block[0] for block in self.body.stream_data]

if len(newData) == 1 or (len(newData) - 1) % 2 != 0:
if (len(newData) - 1) % 2 != 0:
raise StreamBlockValidationError(non_block_errors=[_(
'Rule Combination must follow the <Rule/NestedLogic>'
'<Operator> <Rule/NestedLogic> pattern.')])

iterations = (len(newData) - 1) / 2
for i in range(iterations):
first_rule_index = i * 2
operator_index = (i * 2) + 1
second_rule_index = (i * 2) + 2

if not (
(newData[first_rule_index] == 'Rule' or
newData[first_rule_index] == 'NestedLogic') and
(newData[operator_index] == 'Operator') and
(newData[second_rule_index] == 'Rule' or
newData[second_rule_index] == 'NestedLogic')):
if len(newData) == 1:
if newData[0] == 'NestedLogic':
pass
else:
raise StreamBlockValidationError(non_block_errors=[_(
'Rule Combination must follow the <Rule/NestedLogic> '
'<Operator> <Rule/NestedLogic> pattern.')])
else:
iterations = (len(newData) - 1) / 2
for i in range(iterations):
first_rule_index = i * 2
operator_index = (i * 2) + 1
second_rule_index = (i * 2) + 2

if not (
(newData[first_rule_index] == 'Rule' or
newData[first_rule_index] == 'NestedLogic') and
(newData[operator_index] == 'Operator') and
(newData[second_rule_index] == 'Rule' or
newData[second_rule_index] == 'NestedLogic')):
raise StreamBlockValidationError(non_block_errors=[_(
'Rule Combination must follow the '
'<Rule/NestedLogic> '
'<Operator> <Rule/NestedLogic> pattern.')])
else:
raise StreamBlockValidationError(non_block_errors=[_(
'Rule Combination must follow the <Rule/NestedLogic>'
Expand Down
66 changes: 50 additions & 16 deletions molo/surveys/tests/test_adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ def setUp(self):

self.request.user.segment_groups.add(self.group_1)

self.group_rule_1 = GroupMembershipRule(group=self.group_1)
self.group_rule_2 = GroupMembershipRule(group=self.group_2)
self.logged_in_rule = UserIsLoggedInRule(is_logged_in=True)

def test_get_rule(self):
fake_ds = {
'TimeRule': ['first time rule', 'second time rule'],
Expand All @@ -48,25 +52,19 @@ def test_get_rule(self):
fake_ds["UserIsLoggedInRule"][0])

def test_index_rules_by_type(self):
group_rule_1 = GroupMembershipRule(group=self.group_1)
group_rule_2 = GroupMembershipRule(group=self.group_2)
logged_in_rule = UserIsLoggedInRule(is_logged_in=True)

test_input = [logged_in_rule, group_rule_1, group_rule_2]
test_input = [self.logged_in_rule,
self.group_rule_1,
self.group_rule_2]
expected_output = {
'GroupMembershipRule': [group_rule_1, group_rule_2],
'UserIsLoggedInRule': [logged_in_rule]
'GroupMembershipRule': [self.group_rule_1, self.group_rule_2],
'UserIsLoggedInRule': [self.logged_in_rule]
}

self.assertEqual(
index_rules_by_type(test_input),
expected_output)

def test_transform_into_boolean_list_simple(self):
group_rule_1 = GroupMembershipRule(group=self.group_1)
group_rule_2 = GroupMembershipRule(group=self.group_2)
logged_in_rule = UserIsLoggedInRule(is_logged_in=True)

sample_stream_data = [
{u'type': u'Rule', u'value': u'UserIsLoggedInRule_0'},
{u'type': u'Operator', u'value': u'and'},
Expand All @@ -80,8 +78,8 @@ def test_transform_into_boolean_list_simple(self):
]

sample_indexed_rules = {
'GroupMembershipRule': [group_rule_1, group_rule_2],
'UserIsLoggedInRule': [logged_in_rule]
'GroupMembershipRule': [self.group_rule_1, self.group_rule_2],
'UserIsLoggedInRule': [self.logged_in_rule]
}

self.assertEqual(
Expand All @@ -90,12 +88,41 @@ def test_transform_into_boolean_list_simple(self):
sample_indexed_rules,
self.request
),
[logged_in_rule.test_user(self.request),
[self.logged_in_rule.test_user(self.request),
u'and',
[
group_rule_1.test_user(self.request),
self.group_rule_1.test_user(self.request),
u'or',
self.group_rule_2.test_user(self.request)
]]
)

def test_transform_into_boolean_list_only_nested(self):
sample_stream_data = [
{
u'type': u'NestedLogic',
u'value': {
u'operator': u'or',
u'rule_1': u'UserIsLoggedInRule_0',
u'rule_2': u'GroupMembershipRule_0'}
}
]

sample_indexed_rules = {
'GroupMembershipRule': [self.group_rule_1],
'UserIsLoggedInRule': [self.logged_in_rule]
}

self.assertEqual(
transform_into_boolean_list(
sample_stream_data,
sample_indexed_rules,
self.request
),
[[
self.logged_in_rule.test_user(self.request),
u'or',
group_rule_2.test_user(self.request)
self.group_rule_1.test_user(self.request)
]]
)

Expand Down Expand Up @@ -150,3 +177,10 @@ def test_evaluate_7(self):
[False, "and", False], "or",
[True, 'and', False]])
)

def test_evaluate_8(self):
self.assertEqual(
((False or True)),
evaluate(
[[False, "or", True]])
)

0 comments on commit 9ff3ce3

Please sign in to comment.