Skip to content

Commit c9dd90d

Browse files
chore: mail identity tests
Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
1 parent 12f9c53 commit c9dd90d

5 files changed

Lines changed: 254 additions & 7 deletions

File tree

.github/workflows/integration-tests.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,21 @@ jobs:
2424
- name: Install Stalwart Mail Server
2525
uses: SebastianKrupinski/action-stalwart-install@v1.0.1
2626
with:
27-
admin_password: Password1234
2827
domains: |
2928
[
30-
{"name": "stalwart.local", "description": "Test domain"}
29+
{"name": "example1.com", "description": "Test domain"}
3130
]
3231
users: |
3332
[
3433
{
35-
"email": "user1@stalwart.local",
34+
"email": "user1@example1.com",
3635
"password": "Password1234",
3736
"name": "Test User 1"
3837
}
3938
]
4039
41-
- name: Add stalwart.local to /etc/hosts
42-
run: echo "127.0.0.1 stalwart.local" | sudo tee -a /etc/hosts
40+
- name: Add example1.com to /etc/hosts
41+
run: echo "127.0.0.1 example1.com" | sudo tee -a /etc/hosts
4342

4443
- name: Set up PHP
4544
uses: shivammathur/setup-php@v2

lib/Requests/Mail/MailIdentityParameters.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ public function __construct(&$parameters = null)
1818
parent::__construct($parameters);
1919
}
2020

21+
public function address(string $value): static
22+
{
23+
$this->parameter('email', $value);
24+
return $this;
25+
}
26+
2127
public function name(string $value): static
2228
{
2329
$this->parameter('name', $value);

tests/integration/ClientFactory.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ public static function instance(string $serviceName): Client
2929
$service['identifier'],
3030
$service['secret']
3131
));
32+
$client->configureTransportLogState(true);
33+
$client->configureTransportLogLocation('/tmp/jmap_client.log');
3234
return $client;
3335
}
36+
37+
public static function identifier(string $serviceName): string
38+
{
39+
$servicesFile = __DIR__ . '/../resources/services.json';
40+
$servicesData = file_get_contents($servicesFile);
41+
$servicesData = json_decode($servicesData, true);
42+
return $servicesData[$serviceName]['identifier'];
43+
}
3444
}
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
6+
* SPDX-License-Identifier: AGPL-3.0-or-later
7+
*/
8+
9+
namespace JmapClient\Tests\Integration\Mail;
10+
11+
use JmapClient\Client;
12+
use JmapClient\Requests\Mail\MailIdentityGet as MailIdentityGetRequest;
13+
use JmapClient\Requests\Mail\MailIdentitySet as MailIdentitySetRequest;
14+
use JmapClient\Responses\Mail\MailIdentityGet as MailIdentityGetResponse;
15+
use JmapClient\Responses\Mail\MailIdentityParameters;
16+
use JmapClient\Responses\Mail\MailIdentitySet as MailIdentitySetResponse;
17+
use JmapClient\Session\Account;
18+
use JmapClient\Tests\Integration\ClientFactory;
19+
use PHPUnit\Framework\TestCase;
20+
21+
class MailIdentityTest extends TestCase
22+
{
23+
private Client $client;
24+
private Account $account;
25+
private string $identityEmail = '';
26+
27+
public function setUp(): void
28+
{
29+
parent::setUp();
30+
$this->client = ClientFactory::instance('service1');
31+
$this->client->connect();
32+
$this->account = $this->client->sessionAccountDefault('submission');
33+
34+
// derive the email address from the service config identifier
35+
$this->identityEmail = ClientFactory::identifier('service1');
36+
37+
// create a seed identity so get/set tests always have at least one identity to work with
38+
$seedId = uniqid();
39+
$rSeed = new MailIdentitySetRequest($this->account->id());
40+
$pSeed = $rSeed->create($seedId);
41+
$pSeed->name('Test Identity ' . time());
42+
$pSeed->address($this->identityEmail);
43+
$response = $this->client->perform([$rSeed]);
44+
$result = $response->first()->createSuccess($seedId);
45+
$this->assertNotNull($result, 'Failed to create seed identity');
46+
}
47+
48+
public function tearDown(): void
49+
{
50+
parent::tearDown();
51+
// construct list request
52+
$r0 = new MailIdentityGetRequest($this->account->id());
53+
// transceive
54+
$bundle = $this->client->perform([$r0]);
55+
$response = $bundle->first();
56+
if (!($response instanceof MailIdentityGetResponse)) {
57+
return;
58+
}
59+
$commands = [];
60+
// construct deletion requests for test-created identities
61+
foreach ($response->objects() as $identity) {
62+
if ($identity->deletable() &&
63+
(str_starts_with($identity->name(), 'Test Identity ') ||
64+
str_starts_with($identity->name(), 'Modified Identity ') ||
65+
str_starts_with($identity->name(), 'To Delete Identity '))) {
66+
$rq = new MailIdentitySetRequest($this->account->id());
67+
$rq->delete($identity->id());
68+
$commands[] = $rq;
69+
}
70+
}
71+
// transceive
72+
if (!empty($commands)) {
73+
//$this->client->perform($commands);
74+
}
75+
}
76+
77+
public function testMailIdentityGetAll(): void
78+
{
79+
// construct fetch request
80+
$r0 = new MailIdentityGetRequest($this->account->id());
81+
82+
// transceive
83+
$bundle = $this->client->perform([$r0]);
84+
85+
// verify fetch response — per RFC 8621 §6 servers MUST provide at least one Identity
86+
$this->assertEquals(1, $bundle->tally());
87+
$this->assertInstanceOf(MailIdentityGetResponse::class, $bundle->first());
88+
$results = $bundle->first()->objects();
89+
$this->assertIsArray($results);
90+
$this->assertNotEmpty($results);
91+
foreach ($results as $result) {
92+
$this->assertInstanceOf(MailIdentityParameters::class, $result);
93+
}
94+
}
95+
96+
public function testMailIdentityGetSpecific(): void
97+
{
98+
// retrieve all identities to find a real id
99+
$r0 = new MailIdentityGetRequest($this->account->id());
100+
$bundle = $this->client->perform([$r0]);
101+
$first = $bundle->first()->object(0);
102+
$this->assertInstanceOf(MailIdentityParameters::class, $first);
103+
$identityId = $first->id();
104+
105+
// construct fetch request for a specific identity
106+
$r1 = new MailIdentityGetRequest($this->account->id());
107+
$r1->target($identityId);
108+
109+
// transceive
110+
$bundle = $this->client->perform([$r1]);
111+
112+
// verify fetch response
113+
$this->assertEquals(1, $bundle->tally());
114+
$this->assertInstanceOf(MailIdentityGetResponse::class, $bundle->first());
115+
$result = $bundle->first()->object(0);
116+
$this->assertInstanceOf(MailIdentityParameters::class, $result);
117+
$this->assertEquals($identityId, $result->id());
118+
$this->assertNotEmpty($result->name());
119+
}
120+
121+
public function testMailIdentityGetWithProperties(): void
122+
{
123+
// construct fetch request with limited properties
124+
$r0 = new MailIdentityGetRequest($this->account->id());
125+
$r0->property('id', 'name');
126+
127+
// transceive
128+
$bundle = $this->client->perform([$r0]);
129+
130+
// verify fetch response — unrequested properties should be absent/null
131+
$this->assertEquals(1, $bundle->tally());
132+
$this->assertInstanceOf(MailIdentityGetResponse::class, $bundle->first());
133+
$result = $bundle->first()->object(0);
134+
$this->assertInstanceOf(MailIdentityParameters::class, $result);
135+
$this->assertNotEmpty($result->id());
136+
$this->assertNotNull($result->name());
137+
$this->assertNull($result->address());
138+
}
139+
140+
public function testMailIdentitySetCreate(): void
141+
{
142+
// construct create request
143+
$createId = uniqid();
144+
$r0 = new MailIdentitySetRequest($this->account->id());
145+
$p0 = $r0->create($createId);
146+
$p0->name('Test Identity ' . time());
147+
$p0->address($this->identityEmail);
148+
$p0->signaturePlain('-- Test signature');
149+
150+
// transceive
151+
$bundle = $this->client->perform([$r0]);
152+
153+
// verify create response
154+
$this->assertEquals(1, $bundle->tally());
155+
$this->assertInstanceOf(MailIdentitySetResponse::class, $bundle->first());
156+
$result = $bundle->first()->createSuccess($createId);
157+
$this->assertNotNull($result);
158+
$this->assertArrayHasKey('id', $result);
159+
}
160+
161+
public function testMailIdentitySetUpdate(): void
162+
{
163+
// construct create request
164+
$createId = uniqid();
165+
$r0 = new MailIdentitySetRequest($this->account->id());
166+
$p0 = $r0->create($createId);
167+
$p0->name('Test Identity ' . time());
168+
$p0->address($this->identityEmail);
169+
170+
// transceive
171+
$bundle = $this->client->perform([$r0]);
172+
173+
// extract identity id
174+
$result = $bundle->first()->createSuccess($createId);
175+
$identityId = $result['id'];
176+
177+
// construct modify request
178+
$r1 = new MailIdentitySetRequest($this->account->id());
179+
$p1 = $r1->update($identityId);
180+
$p1->name('Modified Identity ' . time());
181+
$p1->signaturePlain('-- Modified test signature');
182+
183+
// transceive
184+
$bundle = $this->client->perform([$r1]);
185+
186+
// verify modify response
187+
$this->assertEquals(1, $bundle->tally());
188+
$this->assertInstanceOf(MailIdentitySetResponse::class, $bundle->first());
189+
$result = $bundle->first()->updateSuccess($identityId);
190+
$this->assertNotNull($result);
191+
$this->assertArrayHasKey('id', $result);
192+
}
193+
194+
public function testMailIdentitySetDelete(): void
195+
{
196+
// construct create request
197+
$createId = uniqid();
198+
$r0 = new MailIdentitySetRequest($this->account->id());
199+
$p0 = $r0->create($createId);
200+
$p0->name('To Delete Identity ' . time());
201+
$p0->address($this->identityEmail);
202+
203+
// transceive
204+
$bundle = $this->client->perform([$r0]);
205+
206+
// extract identity id
207+
$result = $bundle->first()->createSuccess($createId);
208+
$identityId = $result['id'];
209+
210+
// verify the newly created identity is deletable
211+
$r1 = new MailIdentityGetRequest($this->account->id());
212+
$r1->target($identityId);
213+
$bundle = $this->client->perform([$r1]);
214+
$identity = $bundle->first()->object(0);
215+
$this->assertInstanceOf(MailIdentityParameters::class, $identity);
216+
$this->assertTrue($identity->deletable(), 'Newly created identity should be deletable');
217+
218+
// construct delete request
219+
$r2 = new MailIdentitySetRequest($this->account->id());
220+
$r2->delete($identityId);
221+
222+
// transceive
223+
$bundle = $this->client->perform([$r2]);
224+
225+
// verify delete response
226+
$this->assertEquals(1, $bundle->tally());
227+
$this->assertInstanceOf(MailIdentitySetResponse::class, $bundle->first());
228+
$result = $bundle->first()->deleteSuccess($identityId);
229+
$this->assertNotNull($result);
230+
$this->assertArrayHasKey('id', $result);
231+
}
232+
}

tests/resources/services.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"service1": {
33
"protocol": "http",
4-
"host": "stalwart.local",
4+
"host": "example1.com",
55
"port": 8080,
66
"security": 0,
77
"authentication": "basic",
8-
"identifier": "user1@stalwart.local",
8+
"identifier": "user1@example1.com",
99
"secret": "Password1234"
1010
}
1111
}

0 commit comments

Comments
 (0)