Changeset View
Changeset View
Standalone View
Standalone View
src/tests/Infrastructure/ActivesyncTest.php
- This file was added.
<?php | |||||
namespace Tests\Infrastructure; | |||||
use Tests\TestCase; | |||||
class ActivesyncTest extends TestCase | |||||
{ | |||||
private \GuzzleHttp\Client $client; | |||||
private static function toWbxml($xml) | |||||
{ | |||||
$outputStream = fopen("php://temp", 'r+'); | |||||
$encoder = new \Syncroton_Wbxml_Encoder($outputStream, 'UTF-8', 3); | |||||
Lint: Instantiated class Syncroton_Wbxml_Encoder not found.: Instantiated class Syncroton_Wbxml_Encoder not found. | |||||
$dom = new \DOMDocument(); | |||||
$dom->loadXML($xml); | |||||
$encoder->encode($dom); | |||||
Lint: Call to method encode() on an unknown class Syncroton_Wbxml_Encoder. Call to method encode() on an unknown class Syncroton_Wbxml_Encoder. Lint: Call to method encode() on an unknown class Syncroton_Wbxml_Encoder.: Call to method encode() on an unknown class Syncroton_Wbxml_Encoder. | |||||
rewind($outputStream); | |||||
return stream_get_contents($outputStream); | |||||
} | |||||
private static function fromWbxml($binary) | |||||
{ | |||||
$stream = fopen('php://memory', 'r+'); | |||||
fwrite($stream, $binary); | |||||
rewind($stream); | |||||
$decoder = new \Syncroton_Wbxml_Decoder($stream); | |||||
Lint: Instantiated class Syncroton_Wbxml_Decoder not found. Instantiated class Syncroton_Wbxml_Decoder not found. Lint: Instantiated class Syncroton_Wbxml_Decoder not found.: Instantiated class Syncroton_Wbxml_Decoder not found. | |||||
return $decoder->decode(); | |||||
Lint: Call to method decode() on an unknown class Syncroton_Wbxml_Decoder. Call to method decode() on an unknown class Syncroton_Wbxml_Decoder. Lint: Call to method decode() on an unknown class Syncroton_Wbxml_Decoder.: Call to method decode() on an unknown class Syncroton_Wbxml_Decoder. | |||||
} | |||||
/** | |||||
* {@inheritDoc} | |||||
*/ | |||||
public function setUp(): void | |||||
{ | |||||
parent::setUp(); | |||||
//FIXME test users are probably not created in imap, | |||||
//which is why this fails. So we're using john@kolab.org for now. | |||||
// $user = $this->getTestUser('jane@kolabnow.com'); | |||||
machniakUnsubmitted Done Inline ActionsgetTestUser() is using fake queue. So, you'd have to execute the job(s) manually. Or using IMAP::createUser($user); machniak: getTestUser() is using fake queue. So, you'd have to execute the job(s) manually. Or using… | |||||
// $user->password = "simple123"; | |||||
// $user->save(); | |||||
$this->client = new \GuzzleHttp\Client([ | |||||
'http_errors' => false, // No exceptions | |||||
'base_uri' => "http://roundcube/Microsoft-Server-ActiveSync/", | |||||
machniakUnsubmitted Done Inline ActionsThis should be configurable, please. machniak: This should be configurable, please. | |||||
'verify' => false, | |||||
// 'auth' => [$user->email, $user->password], | |||||
Not Done Inline ActionsI suppose this common code could be moved to getTestUser() (optional). Also, we should not use LDAP::createUser() if LDAP is disabled. machniak: I suppose this common code could be moved to getTestUser() (optional). Also, we should not use… | |||||
'auth' => ['john@kolab.org', 'simple123'], | |||||
'connect_timeout' => 10, | |||||
'timeout' => 10, | |||||
'headers' => [ | |||||
"Content-Type" => "application/xml; charset=utf-8" | |||||
] | |||||
]); | |||||
} | |||||
/** | |||||
* {@inheritDoc} | |||||
*/ | |||||
public function tearDown(): void | |||||
{ | |||||
// $this->deleteTestUser('jane@kolabnow.com'); | |||||
parent::tearDown(); | |||||
} | |||||
public function testOptions() | |||||
{ | |||||
$response = $this->client->request('OPTIONS', ''); | |||||
$this->assertEquals(200, $response->getStatusCode()); | |||||
$this->assertTrue(str_contains($response->getHeader('MS-Server-ActiveSync')[0], '14')); | |||||
machniakUnsubmitted Done Inline ActionsUse assertStringContainsString(). machniak: Use `assertStringContainsString()`. | |||||
Not Done Inline ActionsShould we use setUpBeforeClass() if we use tearDownAfterClass()? Also, we definitely want to remove the created user. machniak: Should we use setUpBeforeClass() if we use tearDownAfterClass()? Also, we definitely want to… | |||||
Not Done Inline ActionsThey are static so I can't set member variables. That's why I ended up using setUp. mollekopf: They are static so I can't set member variables. That's why I ended up using setUp. | |||||
$this->assertTrue(str_contains($response->getHeader('MS-ASProtocolVersions')[0], '14.1')); | |||||
$this->assertTrue(str_contains($response->getHeader('MS-ASProtocolCommands')[0], 'FolderSync')); | |||||
} | |||||
public function testFolderList() | |||||
{ | |||||
$request = <<<EOF | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> | |||||
<FolderSync xmlns="uri:FolderHierarchy"> | |||||
<SyncKey>0</SyncKey> | |||||
</FolderSync> | |||||
EOF; | |||||
$body = self::toWbxml($request); | |||||
$response = $this->client->request( | |||||
'POST', | |||||
'?Cmd=FolderSync&User=john@kolab.org&DeviceId=v140Device&DeviceType=iphone', | |||||
[ | |||||
'headers' => [ | |||||
"Content-Type" => "application/vnd.ms-sync.wbxml", | |||||
'MS-ASProtocolVersion' => "14.0" | |||||
], | |||||
'body' => $body | |||||
] | |||||
); | |||||
$this->assertEquals(200, $response->getStatusCode()); | |||||
$result = self::fromWbxml($response->getBody())->saveXML(); | |||||
$this->assertTrue(str_contains($result, 'INBOX')); | |||||
$this->assertTrue(str_contains($result, 'Drafts')); | |||||
$this->assertTrue(str_contains($result, 'Sent')); | |||||
$this->assertTrue(str_contains($result, 'Trash')); | |||||
$this->assertTrue(str_contains($result, 'Calendar')); | |||||
$this->assertTrue(str_contains($result, 'Contacts')); | |||||
//TODO extract the collectionid for the next step | |||||
} | |||||
public function testInitialSync() | |||||
{ | |||||
$request = <<<EOF | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
Not Done Inline ActionsDebug code. machniak: Debug code. | |||||
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/"> | |||||
<Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase"> | |||||
<Collections> | |||||
<Collection> | |||||
<SyncKey>0</SyncKey> | |||||
<CollectionId>cca1b81c734abbcd669bea90d23e08ae</CollectionId> | |||||
<DeletesAsMoves>0</DeletesAsMoves> | |||||
<GetChanges>0</GetChanges> | |||||
<WindowSize>512</WindowSize> | |||||
<Options> | |||||
<FilterType>0</FilterType> | |||||
<BodyPreference xmlns="uri:AirSyncBase"> | |||||
<Type>1</Type> | |||||
<AllOrNone>1</AllOrNone> | |||||
</BodyPreference> | |||||
</Options> | |||||
</Collection> | |||||
</Collections> | |||||
<WindowSize>16</WindowSize> | |||||
</Sync> | |||||
EOF; | |||||
$body = self::toWbxml($request); | |||||
$response = $this->client->request( | |||||
'POST', | |||||
'?Cmd=Sync&User=john@kolab.org&DeviceId=v140Device&DeviceType=iphone', | |||||
[ | |||||
'headers' => [ | |||||
"Content-Type" => "application/vnd.ms-sync.wbxml", | |||||
'MS-ASProtocolVersion' => "14.0" | |||||
], | |||||
'body' => $body | |||||
] | |||||
); | |||||
$this->assertEquals(200, $response->getStatusCode()); | |||||
$dom = self::fromWbxml($response->getBody()); | |||||
$collections = $dom->getElementsByTagName('Collection'); | |||||
$this->assertEquals(1, $collections->length); | |||||
$collection = $collections->item(0); | |||||
$this->assertEquals("Class", $collection->childNodes->item(0)->nodeName); | |||||
$this->assertEquals("Calendar", $collection->childNodes->item(0)->nodeValue); | |||||
$this->assertEquals("SyncKey", $collection->childNodes->item(1)->nodeName); | |||||
$this->assertEquals("1", $collection->childNodes->item(1)->nodeValue); | |||||
$this->assertEquals("Status", $collection->childNodes->item(3)->nodeName); | |||||
$this->assertEquals("1", $collection->childNodes->item(3)->nodeValue); | |||||
} | |||||
} |
Instantiated class Syncroton_Wbxml_Encoder not found.