Skip to content

Commit

Permalink
Merge pull request #124 from norkunas/new-apis
Browse files Browse the repository at this point in the history
Add new api endpoints
  • Loading branch information
norkunas authored Sep 3, 2019
2 parents 1240f5f + 1402712 commit 8a4e80b
Show file tree
Hide file tree
Showing 10 changed files with 323 additions and 2 deletions.
34 changes: 34 additions & 0 deletions src/Apps.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,38 @@ public function update($id, array $data)
'Authorization' => 'Basic '.$this->api->getConfig()->getUserAuthKey(),
], json_encode($data));
}

/**
* Create a new segment for application with provided data.
*
* @param string $appId ID of your application
* @param array $data Segment Data
*
* @return array
*/
public function createSegment($appId, array $data)
{
$data = $this->resolverFactory->createSegmentResolver()->resolve($data);

return $this->api->request('POST', '/apps/'.$appId.'/segments', [
'Authorization' => 'Basic '.$this->api->getConfig()->getApplicationAuthKey(),
], json_encode($data));
}

/**
* Delete existing segment from your application.
*
* Application auth key must be set.
*
* @param string $appId Application ID
* @param string $segmentId Segment ID
*
* @return array
*/
public function deleteSegment($appId, $segmentId)
{
return $this->api->request('DELETE', '/apps/'.$appId.'/segments/'.$segmentId, [
'Authorization' => 'Basic '.$this->api->getConfig()->getApplicationAuthKey(),
]);
}
}
22 changes: 22 additions & 0 deletions src/Notifications.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,26 @@ public function cancel($id)
'Authorization' => 'Basic '.$this->api->getConfig()->getApplicationAuthKey(),
]);
}

/**
* View the devices sent a notification.
*
* Application authentication key and ID must be set.
*
* @param string $id Notification ID
* @param array $data
*
* @return array
*/
public function history($id, array $data)
{
$url = '/notifications/'.$id.'/history?app_id='.$this->api->getConfig()->getApplicationId();

$data = $this->resolverFactory->createNotificationResolver()->resolve($data);

return $this->api->request('POST', $url, [
'Authorization' => 'Basic '.$this->api->getConfig()->getApplicationAuthKey(),
'Cache-Control' => 'no-cache',
], json_encode($data));
}
}
22 changes: 22 additions & 0 deletions src/Resolver/NotificationHistoryResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace OneSignal\Resolver;

use Symfony\Component\OptionsResolver\OptionsResolver;

class NotificationHistoryResolver implements ResolverInterface
{
/**
* {@inheritdoc}
*/
public function resolve(array $data)
{
return (new OptionsResolver())
->setRequired('events')
->setAllowedTypes('events', 'string')
->setAllowedValues('events', ['sent', 'clicked'])
->setRequired('email')
->setAllowedTypes('email', 'string')
->resolve($data);
}
}
10 changes: 10 additions & 0 deletions src/Resolver/ResolverFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ public function createAppResolver()
return new AppResolver();
}

public function createSegmentResolver()
{
return new SegmentResolver();
}

public function createDeviceSessionResolver()
{
return new DeviceSessionResolver();
Expand Down Expand Up @@ -47,4 +52,9 @@ public function createNotificationResolver()
{
return new NotificationResolver($this->config);
}

public function createNotificationHistoryResolver()
{
return new NotificationHistoryResolver();
}
}
40 changes: 40 additions & 0 deletions src/Resolver/SegmentResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace OneSignal\Resolver;

use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

class SegmentResolver implements ResolverInterface
{
/**
* {@inheritdoc}
*/
public function resolve(array $data)
{
return (new OptionsResolver())
->setDefined('id')
->setAllowedTypes('id', 'string')
->setRequired('name')
->setAllowedTypes('name', 'string')
->setDefined('filters')
->setAllowedTypes('filters', 'array')
->setNormalizer('filters', function (Options $options, array $values) {
return $this->normalizeFilters($options, $values);
})
->resolve($data);
}

private function normalizeFilters(Options $options, array $values)
{
$filters = [];

foreach ($values as $filter) {
if (isset($filter['field']) || isset($filter['operator'])) {
$filters[] = $filter;
}
}

return $filters;
}
}
4 changes: 2 additions & 2 deletions tests/OneSignal/Tests/AbstractApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ abstract class AbstractApiTest extends TestCase
protected $api;

/**
* @var ResolverFactory
* @var ResolverFactory|\PHPUnit_Framework_MockObject_MockObject
*/
protected $resolverFactory;

Expand All @@ -28,7 +28,7 @@ public function setUp()

$resolverFactory = $this->createMock(ResolverFactory::class);
$resolverMethods = array_filter(get_class_methods($resolverFactory), function ($method) {
return strpos($method, 'create') === 0;
return 0 === strpos($method, 'create');
});
foreach ($resolverMethods as $method) {
$resolverFactory->method($method)->willReturn($mockResolver);
Expand Down
28 changes: 28 additions & 0 deletions tests/OneSignal/Tests/AppsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,32 @@ public function testUpdate()
$this->resolverFactory->expects($this->once())->method('createAppResolver');
$this->assertEquals($expectedRequest, $this->apps->update($fakeId, ['data' => 'myData']));
}

public function testCreateSegment()
{
$fakeAppId = '85f0e7eb-df11-4a86-ab5a-603a6c0a14c6';
$expectedRequest = [
'POST',
'/apps/'.$fakeAppId.'/segments',
['Authorization' => 'Basic fakeApplicationAuthKey'],
'{"id":"52d5a7cb-59fe-4d0c-a0b9-9a39a21475ad","name":"Custom Segment","filters":[{"field":"session_count","relation":">","value":"1"},{"operator":"AND"},{"field":"tag","relation":"!=","key":"tag_key","value":"1"},{"operator":"OR"},{"field":"last_session","relation":"<","value":"30"}]}',
];

$this->resolverFactory->expects($this->once())->method('createSegmentResolver');
$this->assertEquals($expectedRequest, $this->apps->createSegment($fakeAppId, ['id' => '52d5a7cb-59fe-4d0c-a0b9-9a39a21475ad', 'name' => 'Custom Segment', 'filters' => [['field' => 'session_count', 'relation' => '>', 'value' => '1'], ['operator' => 'AND'], ['field' => 'tag', 'relation' => '!=', 'key' => 'tag_key', 'value' => '1'], ['operator' => 'OR'], ['field' => 'last_session', 'relation' => '<', 'value' => '30']]]));
}

public function testDeleteSegment()
{
$fakeAppId = '85f0e7eb-df11-4a86-ab5a-603a6c0a14c6';
$fakeSegmentId = 'a98c618f-f680-4b3a-9cdd-0957873c13b6';
$expectedRequest = [
'DELETE',
'/apps/'.$fakeAppId.'/segments/'.$fakeSegmentId,
['Authorization' => 'Basic fakeApplicationAuthKey'],
null,
];

$this->assertEquals($expectedRequest, $this->apps->deleteSegment($fakeAppId, $fakeSegmentId));
}
}
13 changes: 13 additions & 0 deletions tests/OneSignal/Tests/NotificationsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,17 @@ public function testCancel()

$this->assertEquals($expectedRequest, $this->notifications->cancel($fakeId));
}

public function testHistory()
{
$fakeId = 1234;
$expectedRequest = [
'POST',
'/notifications/'.$fakeId.'/history?app_id=fakeApplicationId',
['Authorization' => 'Basic fakeApplicationAuthKey', 'Cache-Control' => 'no-cache'],
'{"events":"sent","email":"example@example.com"}',
];

$this->assertEquals($expectedRequest, $this->notifications->history($fakeId, ['events' => 'sent', 'email' => 'example@example.com']));
}
}
62 changes: 62 additions & 0 deletions tests/OneSignal/Tests/Resolver/NotificationHistoryResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace OneSignal\Tests\Resolver;

use OneSignal\Resolver\NotificationHistoryResolver;
use PHPUnit\Framework\TestCase;

class NotificationHistoryResolverTest extends TestCase
{
/**
* @var NotificationHistoryResolver
*/
private $notificationHistoryResolver;

public function setUp()
{
$this->notificationHistoryResolver = new NotificationHistoryResolver();
}

public function testResolveWithValidValues()
{
$expectedData = [
'events' => 'sent',
'email' => 'example@example.com',
];

$this->assertEquals($expectedData, $this->notificationHistoryResolver->resolve($expectedData));
}

/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\MissingOptionsException
*/
public function testResolveWithMissingRequiredValue()
{
$this->notificationHistoryResolver->resolve([]);
}

public function wrongValueTypesProvider()
{
return [
[['events' => 666, 'email' => 'example@example.com']],
[['events' => 'sent', 'email' => 666]],
];
}

/**
* @dataProvider wrongValueTypesProvider
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testResolveWithWrongValueTypes($wrongOption)
{
$this->notificationHistoryResolver->resolve($wrongOption);
}

/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
*/
public function testResolveWithWrongOption()
{
$this->notificationHistoryResolver->resolve(['events' => 'sent', 'wrongOption' => 'wrongValue']);
}
}
90 changes: 90 additions & 0 deletions tests/OneSignal/Tests/Resolver/SegmentResolverTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace OneSignal\Tests\Resolver;

use OneSignal\Resolver\SegmentResolver;
use OneSignal\Tests\PrivateAccessorTrait;
use PHPUnit\Framework\TestCase;
use Symfony\Component\OptionsResolver\OptionsResolver;

class SegmentResolverTest extends TestCase
{
use PrivateAccessorTrait;

/**
* @var SegmentResolver
*/
private $segmentResolver;

public function setUp()
{
$this->segmentResolver = new SegmentResolver();
}

public function testResolveWithValidValues()
{
$expectedData = [
'id' => '52d5a7cb-59fe-4d0c-a0b9-9a39a21475ad',
'name' => 'Custom Segment',
'filters' => [],
];

$this->assertEquals($expectedData, $this->segmentResolver->resolve($expectedData));
}

public function wrongValueTypesProvider()
{
return [
[['id' => 666, 'name' => '']],
[['name' => 666]],
[['filters' => 666, 'name' => '']],
];
}

/**
* @dataProvider wrongValueTypesProvider
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testResolveWithWrongValueTypes($wrongOption)
{
$this->segmentResolver->resolve($wrongOption);
}

/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
*/
public function testResolveWithWrongOption()
{
$this->segmentResolver->resolve(['wrongOption' => 'wrongValue']);
}

/****** Private functions testing ******/

public function testNormalizeFilters()
{
$method = $this->getPrivateMethod(SegmentResolver::class, 'normalizeFilters');

$inputData = [
new OptionsResolver(),
[
['wrongField' => 'wrongValue'],
['field' => 'session_count', 'relation' => '>', 'value' => '1'],
['operator' => 'AND'],
['field' => 'tag', 'relation' => '!=', 'key' => 'tag_key', 'value' => '1'],
['operator' => 'OR'],
['field' => 'last_session', 'relation' => '<', 'value' => '30'],
],
];

$expectedData =
[
['field' => 'session_count', 'relation' => '>', 'value' => '1'],
['operator' => 'AND'],
['field' => 'tag', 'relation' => '!=', 'key' => 'tag_key', 'value' => '1'],
['operator' => 'OR'],
['field' => 'last_session', 'relation' => '<', 'value' => '30'],
];

$this->assertEquals($expectedData, $method->invokeArgs($this->segmentResolver, $inputData));
}
}

0 comments on commit 8a4e80b

Please sign in to comment.