Skip to content

Commit 3b95bb1

Browse files
committed
Add tests for constraints
1 parent 0e5e79b commit 3b95bb1

File tree

6 files changed

+146
-33
lines changed

6 files changed

+146
-33
lines changed

models/UnleashSDK.cfc

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ component singleton accessors="true" {
3434
if ( !satisfiesConstraints( strategyData.constraints ) ) {
3535
continue;
3636
}
37-
37+
3838
param strategyData.parameters = {};
3939
if ( !strategy.isEnabled( strategyData.parameters, getContext() ) ) {
4040
return false;
@@ -125,19 +125,20 @@ component singleton accessors="true" {
125125

126126
private boolean function satisfiesConstraints( required array constraints ) {
127127
for ( var constraint in arguments.constraints ) {
128-
var satisfies = strategy.satisfiesConstraint(
129-
contextName = constraint.contextName,
130-
operator = constraint.operator,
131-
values = constraint.values,
132-
context = getContext()
133-
);
134-
if ( !satisfies ) {
128+
if ( !satisfiesConstraint( constraint ) ) {
135129
return false;
136130
}
137131
}
138132
return true;
139133
}
140134

135+
private boolean function satisfiesConstraint( required struct constraint ) {
136+
var context = getContext();
137+
var contextValue = context[ arguments.constraint.contextName ];
138+
var valuePresent = arrayContainsNoCase( arguments.constraint.values, contextValue );
139+
return arguments.constraint.operator == "IN" ? valuePresent : !valuePresent;
140+
}
141+
141142
private struct function getContext() {
142143
param request.unleashContext = generateContext();
143144
return request.unleashContext;

models/strategies/DefaultStrategy.cfc

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
11
component implements="IStrategy" singleton {
22

3-
public boolean function satisfiesConstraint(
4-
required string contextName,
5-
required string operator,
6-
required array values,
7-
required struct context
8-
) {
9-
return true; // spike
10-
}
11-
123
public boolean function isEnabled(
134
required struct parameters,
145
required struct context

models/strategies/IStrategy.cfc

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
11
interface {
22

3-
public boolean function satisfiesConstraint(
4-
required string contextName,
5-
required string operator,
6-
required array values,
7-
required struct context
8-
);
9-
103
public boolean function isEnabled(
114
required struct parameters,
125
required struct context

models/strategies/UserWithIdStrategy.cfc

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
11
component implements="IStrategy" singleton {
22

3-
public boolean function satisfiesConstraint(
4-
required string contextName,
5-
required string operator,
6-
required array values,
7-
required struct context
8-
) {
9-
return true; // spike
10-
}
11-
123
public boolean function isEnabled(
134
required struct parameters,
145
required struct context
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
component extends="tests.resources.ModuleIntegrationSpec" {
2+
3+
property name="cache" inject="cachebox:default";
4+
5+
function beforeAll() {
6+
super.beforeAll();
7+
}
8+
9+
function run() {
10+
describe( "Constraints", function() {
11+
it( "can skip strategies based on constraints", function() {
12+
var unleash = prepareMock( getInstance( "UnleashSDK@unleashsdk" ) );
13+
unleash.$( "getContext", {
14+
"appName": "unleashsdk-tests",
15+
"environment": "testing",
16+
"userId": "1",
17+
"sessionId": "1",
18+
"remoteAddress": CGI.REMOTE_ADDR
19+
} );
20+
unleash.$( "getFeature", {
21+
"stale": false,
22+
"variants": "",
23+
"enabled": true,
24+
"type": "release",
25+
"name": "feature-1",
26+
"strategies": [
27+
{
28+
"name": "default",
29+
"parameters": {},
30+
"constraints": [
31+
{
32+
"contextName": "environment",
33+
"operator": "IN",
34+
"values": [ "dev", "testing" ]
35+
},
36+
{
37+
"contextName": "appName",
38+
"operator": "NOT_IN",
39+
"values": [ "unleashsdk-tests" ]
40+
}
41+
]
42+
},
43+
{
44+
"name": "userWithId",
45+
"parameters": {
46+
"userIds": "2,3,4"
47+
}
48+
}
49+
]
50+
} );
51+
expect( unleash.isEnabled( "feature-1" ) ).toBeFalse();
52+
// unleash.$( "getContext", {
53+
// "appName": "unleashsdk-not-tests",
54+
// "environment": "testing",
55+
// "userId": "1",
56+
// "sessionId": "1",
57+
// "remoteAddress": CGI.REMOTE_ADDR
58+
// } );
59+
// expect( unleash.isEnabled( "feature-1" ) ).toBeTrue();
60+
} );
61+
62+
it( "all strategies that pass constraints must be enabled for the feature to be enabled", function() {
63+
var unleash = prepareMock( getInstance( "UnleashSDK@unleashsdk" ) );
64+
unleash.$( "getContext", {
65+
"appName": "unleashsdk-not-tests",
66+
"environment": "testing",
67+
"userId": "1",
68+
"sessionId": "1",
69+
"remoteAddress": CGI.REMOTE_ADDR
70+
} );
71+
unleash.$( "getFeature", {
72+
"stale": false,
73+
"variants": "",
74+
"enabled": true,
75+
"type": "release",
76+
"name": "feature-1",
77+
"strategies": [
78+
{
79+
"name": "default",
80+
"parameters": {},
81+
"constraints": [
82+
{
83+
"contextName": "environment",
84+
"operator": "IN",
85+
"values": [ "dev", "testing" ]
86+
},
87+
{
88+
"contextName": "appName",
89+
"operator": "NOT_IN",
90+
"values": [ "unleashsdk-tests" ]
91+
}
92+
]
93+
},
94+
{
95+
"name": "userWithId",
96+
"parameters": {
97+
"userIds": "1,2,3,4"
98+
}
99+
}
100+
]
101+
} );
102+
expect( unleash.isEnabled( "feature-1" ) ).toBeTrue();
103+
} );
104+
} );
105+
}
106+
107+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
component extends="tests.resources.ModuleIntegrationSpec" {
2+
3+
property name="cache" inject="cachebox:default";
4+
5+
function beforeAll() {
6+
super.beforeAll();
7+
variables.strategy = getInstance( "DefaultStrategy@unleashsdk" );
8+
}
9+
10+
function run() {
11+
describe( "DefaultStrategy", function() {
12+
it( "returns true for any params and context", function() {
13+
var result = variables.strategy.isEnabled( {}, getTestContext() );
14+
expect( result ).toBeTrue();
15+
} );
16+
} );
17+
}
18+
19+
function getTestContext( struct overrides = {} ) {
20+
structAppend( arguments.overrides, {
21+
"appName": "unleashsdk-tests",
22+
"environment": "testing",
23+
"userId": "1",
24+
"sessionId": "1",
25+
"remoteAddress": CGI.REMOTE_ADDR
26+
}, false );
27+
return arguments.overrides;
28+
}
29+
30+
}

0 commit comments

Comments
 (0)