Skip to content

Commit

Permalink
Merge 9aea1e1 into 7073e25
Browse files Browse the repository at this point in the history
  • Loading branch information
rashidsp committed Mar 28, 2019
2 parents 7073e25 + 9aea1e1 commit 4766af1
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 5 deletions.
25 changes: 25 additions & 0 deletions src/Optimizely/Enums/DecisionInfoTypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
/**
* Copyright 2019, Optimizely
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace Optimizely\Enums;

class DecisionInfoTypes
{
const EXPERIMENT = "experiment";
const FEATURE = "feature";
const FEATURE_VARIABLE = "feature_variable";
}
3 changes: 2 additions & 1 deletion src/Optimizely/Notification/NotificationType.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Copyright 2017, Optimizely Inc and Contributors
* Copyright 2017, 2019, Optimizely Inc and Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,6 +20,7 @@ class NotificationType
{
// format is EVENT: list of parameters to callback.
const ACTIVATE = "ACTIVATE:experiment, user_id, attributes, variation, event";
const DECISION = "DECISION:type, user_id, attributes, decision_info";
const TRACK = "TRACK:event_key, user_id, attributes, event_tags, event";

public static function isNotificationTypeValid($notification_type)
Expand Down
21 changes: 17 additions & 4 deletions src/Optimizely/Optimizely.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use Optimizely\DecisionService\FeatureDecision;
use Optimizely\Entity\Experiment;
use Optimizely\Entity\FeatureVariable;
use Optimizely\Enums\DecisionInfoTypes;
use Optimizely\ErrorHandler\ErrorHandlerInterface;
use Optimizely\ErrorHandler\NoOpErrorHandler;
use Optimizely\Event\Builder\EventBuilder;
Expand Down Expand Up @@ -405,11 +406,23 @@ public function getVariation($experimentKey, $userId, $attributes = null)
}

$variation = $this->_decisionService->getVariation($experiment, $userId, $attributes);
if (is_null($variation)) {
return null;
}
$variationKey = ($variation === null) ? null : $variation->getKey();

return $variation->getKey();
$attributes = $attributes ?: [];
$this->notificationCenter->sendNotifications(
NotificationType::DECISION,
array(
DecisionInfoTypes::EXPERIMENT,
$userId,
$attributes,
(object) array(
'experimentKey'=> $experiment->getKey(),
'variationKey'=> $variationKey
)
)
);

return $variationKey;
}

/**
Expand Down
137 changes: 137 additions & 0 deletions tests/OptimizelyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Monolog\Logger;
use Optimizely\DecisionService\DecisionService;
use Optimizely\DecisionService\FeatureDecision;
use Optimizely\Enums\DecisionInfoTypes;
use Optimizely\ErrorHandler\NoOpErrorHandler;
use Optimizely\Event\LogEvent;
use Optimizely\Exceptions\InvalidAttributeException;
Expand Down Expand Up @@ -663,6 +664,72 @@ public function testActivateExperimentNotRunning()
$this->assertNull($optimizelyMock->activate('paused_experiment', 'test_user', null));
}

public function testActivateCallsDecisionListenerWhenUserInExperiment()
{
$userAttributes = [
'device_type' => 'iPhone',
'company' => 'Optimizely',
'location' => 'San Francisco'
];

$optimizelyMock = $this->getMockBuilder(Optimizely::class)
->setConstructorArgs(array($this->datafile, new ValidEventDispatcher(), $this->loggerMock))
->setMethods(array('sendImpressionEvent'))
->getMock();

$arrayParam = array(
DecisionInfoTypes::EXPERIMENT,
'test_user',
[
'device_type' => 'iPhone',
'company' => 'Optimizely',
'location' => 'San Francisco'
],
(object) array(
'experimentKey'=> 'test_experiment',
'variationKey'=> 'control'
)
);
$this->notificationCenterMock->expects($this->once())
->method('sendNotifications')
->with(
NotificationType::DECISION,
$arrayParam
);
$optimizelyMock->notificationCenter = $this->notificationCenterMock;

// Call activate
$optimizelyMock->activate('test_experiment', 'test_user', $userAttributes);
}

public function testActivateCallsDecisionListenerWhenUserNotInExperiment()
{
$optimizelyMock = $this->getMockBuilder(Optimizely::class)
->setConstructorArgs(array($this->datafile, new ValidEventDispatcher(), $this->loggerMock))
->setMethods(array('sendImpressionEvent'))
->getMock();

$arrayParam = array(
DecisionInfoTypes::EXPERIMENT,
'test_user',
[],
(object) array(
'experimentKey'=> 'test_experiment',
'variationKey'=> null
)
);
$this->notificationCenterMock->expects($this->once())
->method('sendNotifications')
->with(
NotificationType::DECISION,
$arrayParam
);
$optimizelyMock->notificationCenter = $this->notificationCenterMock;

// Call activate
$optimizelyMock->activate('test_experiment', 'test_user');
}

public function testGetVariationInvalidOptimizelyObject()
{
$optlyObject = new Optimizely('Random datafile', null, new DefaultLogger(Logger::INFO, self::OUTPUT_STREAM));
Expand Down Expand Up @@ -2096,6 +2163,76 @@ public function testGetVariationBucketingIdAttribute()
$this->assertNull($variationKey, sprintf('Invalid variation key "%s" for getVariation with bucketing ID "%s".', $variationKey, $this->testBucketingIdControl));
}

public function testGetVariationCallsDecisionListenerWhenUserInExperiment()
{
$userAttributes = [
'device_type' => 'iPhone',
'company' => 'Optimizely',
'location' => 'San Francisco'
];

$optimizelyMock = $this->getMockBuilder(Optimizely::class)
->setConstructorArgs(array($this->datafile, new ValidEventDispatcher(), $this->loggerMock))
->setMethods(array('sendImpressionEvent'))
->getMock();

$arrayParam = array(
DecisionInfoTypes::EXPERIMENT,
'test_user',
[
'device_type' => 'iPhone',
'company' => 'Optimizely',
'location' => 'San Francisco'
],
(object) array(
'experimentKey'=> 'test_experiment',
'variationKey'=> 'control'
)
);
$this->notificationCenterMock->expects($this->once())
->method('sendNotifications')
->with(
NotificationType::DECISION,
$arrayParam
);
$optimizelyMock->notificationCenter = $this->notificationCenterMock;

// Call getVariation
$optimizelyMock->getVariation('test_experiment', 'test_user', $userAttributes);
}

public function testGetVariationCallsDecisionListenerWhenUserNotInExperiment()
{
$userAttributes = [
'device_type' => 'android'
];

$optimizelyMock = $this->getMockBuilder(Optimizely::class)
->setConstructorArgs(array($this->datafile, new ValidEventDispatcher(), $this->loggerMock))
->setMethods(array('sendImpressionEvent'))
->getMock();

$arrayParam = array(
DecisionInfoTypes::EXPERIMENT,
'test_user',
['device_type' => 'android'],
(object) array(
'experimentKey'=> 'test_experiment',
'variationKey'=> null
)
);
$this->notificationCenterMock->expects($this->once())
->method('sendNotifications')
->with(
NotificationType::DECISION,
$arrayParam
);
$optimizelyMock->notificationCenter = $this->notificationCenterMock;

// Call getVariation
$optimizelyMock->getVariation('test_experiment', 'test_user', $userAttributes);
}

public function testIsFeatureEnabledGivenInvalidDataFile()
{
$optlyObject = new Optimizely('Random datafile', null, new DefaultLogger(Logger::INFO, self::OUTPUT_STREAM));
Expand Down

0 comments on commit 4766af1

Please sign in to comment.