Skip to content

Commit b818d00

Browse files
committed
Add various tests
1 parent c0bb979 commit b818d00

16 files changed

+693
-23
lines changed

README.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ $attachmentsStorage = new AttachmentStorage();
6363

6464
$attachmentsStorage->requestAttachments()->add(
6565
Attachment::create(
66-
'your.pdf',
67-
FileStream::create('path/to/your.pdf', FileStream::READ_MODE),
66+
name: 'file',
67+
filename: 'your.pdf',
68+
content: FileStream::create('path/to/your.pdf', FileStream::READ_MODE),
6869
)
6970
);
7071
$yourSoapClient->request('Foo', $soapPayload);
@@ -126,8 +127,9 @@ use Soap\Psr18AttachmentsMiddleware\Attachment\Attachment;
126127
// These attachments will be automatically added to the AttachmentStorageInterface and a <xop:Include> element will be added to your request instead.
127128
$yourSoapPayload = (object) [
128129
'file' => Attachment::create(
129-
'your.pdf',
130-
FileStream::create('path/to/your.pdf', FileStream::READ_MODE)
130+
name: 'file',
131+
filename: 'your.pdf',
132+
content: FileStream::create('path/to/your.pdf', FileStream::READ_MODE)
131133
)
132134
];
133135

composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
"php-soap/encoding": "^0.16.0",
3434
"vimeo/psalm": "^5.26",
3535
"php-standard-library/psalm-plugin": "^2.3",
36-
"phpunit/phpunit": "^10.5.40"
36+
"phpunit/phpunit": "^10.5.40",
37+
"php-http/mock-client": "^1.6"
3738
},
3839
"config": {
3940
"allow-plugins": {

src/Attachment/Attachment.php

+5
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
final readonly class Attachment
99
{
1010
/**
11+
* @param string $filename - The name of the file inside the Content-Disposition header.
12+
* @param string $name - The name of the attachment inside the Content-Disposition header.
1113
* @param ResourceStream<resource> $content
1214
*/
1315
public function __construct(
1416
public string $id,
17+
public string $name,
1518
public string $filename,
1619
public string $mimeType,
1720
public ResourceStream $content,
@@ -22,6 +25,7 @@ public function __construct(
2225
* @param ResourceStream<resource> $content
2326
*/
2427
public static function create(
28+
string $name,
2529
string $filename,
2630
ResourceStream $content,
2731
?string $mimeType = null,
@@ -30,6 +34,7 @@ public static function create(
3034

3135
return new self(
3236
IdGenerator::generate(),
37+
$name,
3338
$filename,
3439
$mimeType,
3540
$content

src/Attachment/AttachmentsCollection.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Countable;
66
use IteratorAggregate;
77
use Soap\Psr18AttachmentsMiddleware\Exception\AttachmentNotFoundException;
8+
use Traversable;
89

910
/**
1011
* @template-implements \IteratorAggregate<int, Attachment>
@@ -24,7 +25,7 @@ public function __construct(Attachment ... $attachments)
2425
$this->attachments = $attachments;
2526
}
2627

27-
public function getIterator(): iterable
28+
public function getIterator(): Traversable
2829
{
2930
yield from $this->attachments;
3031
}

src/Multipart/RequestBuilder.php

+20-16
Original file line numberDiff line numberDiff line change
@@ -38,26 +38,30 @@ public function __invoke(
3838

3939
$builder = new MultipartStreamBuilder($this->streamFactory);
4040

41-
$builder->addData($request->getBody(), [
42-
'Content-Type' => match ($attachmentType) {
43-
AttachmentType::Swa => 'text/xml; charset=UTF-8',
44-
AttachmentType::Mtom => 'application/xop+xml; charset=UTF-8; type=application/soap+xml',
45-
},
46-
'Content-ID' => 'soaprequest'
47-
]);
41+
$builder->addData(
42+
(string) $request->getBody(),
43+
[
44+
'Content-Type' => match ($attachmentType) {
45+
AttachmentType::Swa => 'text/xml; charset=UTF-8',
46+
AttachmentType::Mtom => 'application/xop+xml; charset=UTF-8; type=application/soap+xml',
47+
},
48+
'Content-ID' => 'soaprequest'
49+
]
50+
);
4851

4952
/** @var Attachment $attachment */
5053
foreach ($attachments as $attachment) {
51-
$builder->addResource(
52-
$attachment->filename,
53-
$attachment->content->unwrap(),
54+
$builder->addData(
55+
$attachment->content->rewind()->unwrap(),
5456
[
55-
'filename' => $attachment->filename,
56-
'headers' => [
57-
'Content-ID' => $attachment->id,
58-
'Content-Type' => $attachment->mimeType,
59-
'Content-Transfer-Encoding' => 'binary',
60-
]
57+
'Content-ID' => $attachment->id,
58+
'Content-Type' => $attachment->mimeType,
59+
'Content-Disposition' => sprintf(
60+
'attachment; name="%s"; filename="%s"',
61+
$attachment->name,
62+
$attachment->filename
63+
),
64+
'Content-Transfer-Encoding' => 'binary',
6165
]
6266
);
6367
}

src/Multipart/ResponseBuilder.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ public function __invoke(
5656

5757
if (($start && $id === $start) || $mimeType === $soapType) {
5858
$mainPart = $part;
59-
break;
59+
continue;
6060
}
6161

6262
$attachments->add(new Attachment(
6363
$id ?: IdGenerator::generate(),
64+
$name = $part->getName() ?? 'unknown',
6465
$part->getFileName() ?? 'unknown',
6566
$mimeType,
6667
TmpStream::create()->write($part->getBody())->rewind(),

tests/Unit/Attachment/AttachmentTest.php

+4
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ public function it_can_load_attachment(): void
1414
{
1515
$attachment = new Attachment(
1616
'id',
17+
'name',
1718
'filename',
1819
'mimeType',
1920
$stream = MemoryStream::create()
2021
);
2122

2223
static::assertSame('id', $attachment->id);
24+
static::assertSame('name', $attachment->name);
2325
static::assertSame('filename', $attachment->filename);
2426
static::assertSame('mimeType', $attachment->mimeType);
2527
static::assertSame($stream, $attachment->content);
@@ -29,11 +31,13 @@ public function it_can_load_attachment(): void
2931
public function it_can_create_an_attachment(): void
3032
{
3133
$attachment = Attachment::create(
34+
'name',
3235
'filename.pdf',
3336
$stream = MemoryStream::create(),
3437
);
3538

3639
static::assertNotEmpty($attachment->id);
40+
static::assertNotEmpty($attachment->name);
3741
static::assertSame('filename.pdf', $attachment->filename);
3842
static::assertSame('application/pdf', $attachment->mimeType);
3943
static::assertSame($stream, $attachment->content);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace SoapTest\Psr18AttachmentsMiddleware\Unit\Attachment;
4+
5+
use Phpro\ResourceStream\Factory\MemoryStream;
6+
use PHPUnit\Framework\Attributes\Test;
7+
use PHPUnit\Framework\TestCase;
8+
use Soap\Psr18AttachmentsMiddleware\Attachment\Attachment;
9+
use Soap\Psr18AttachmentsMiddleware\Attachment\AttachmentsCollection;
10+
use Soap\Psr18AttachmentsMiddleware\Exception\AttachmentNotFoundException;
11+
12+
final class AttachmentsCollectionTest extends TestCase
13+
{
14+
#[Test]
15+
public function it_can_contain_attachments(): void
16+
{
17+
$collection = new AttachmentsCollection(
18+
$attachment1 = Attachment::create('file', 'filename.pdf', MemoryStream::create()),
19+
$attachment2 = Attachment::create('file', 'filename.jpg', MemoryStream::create()),
20+
);
21+
22+
static::assertCount(2, $collection);
23+
static::assertSame([$attachment1, $attachment2], [...$collection]);
24+
}
25+
26+
#[Test]
27+
public function it_can_add_an_item_mutably(): void
28+
{
29+
$collection = new AttachmentsCollection();
30+
$collection->add($attachment = Attachment::create('file', 'filename.pdf', MemoryStream::create()));
31+
32+
static::assertCount(1, $collection);
33+
static::assertSame([$attachment], [...$collection]);
34+
}
35+
36+
#[Test]
37+
public function it_can_find_an_attachment_by_id(): void
38+
{
39+
$collection = new AttachmentsCollection(
40+
$attachment1 = Attachment::create('file', 'filename.pdf', MemoryStream::create()),
41+
$attachment2 = Attachment::create('file', 'filename.jpg', MemoryStream::create()),
42+
);
43+
44+
static::assertSame($attachment1, $collection->findById($attachment1->id));
45+
}
46+
47+
#[Test]
48+
public function it_can_fail_finding_an_attachment_by_id(): void
49+
{
50+
$collection = new AttachmentsCollection(
51+
Attachment::create('file', 'filename.pdf', MemoryStream::create()),
52+
);
53+
54+
$this->expectExceptionObject(AttachmentNotFoundException::withId('not-found'));
55+
$collection->findById('not-found');
56+
}
57+
}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace SoapTest\Psr18AttachmentsMiddleware\Unit\Attachment;
4+
5+
use PHPUnit\Framework\Attributes\Test;
6+
use PHPUnit\Framework\TestCase;
7+
use Soap\Psr18AttachmentsMiddleware\Attachment\IdGenerator;
8+
9+
final class IdGeneratorTest extends TestCase
10+
{
11+
#[Test]
12+
public function it_can_generate_a_random_id(): void
13+
{
14+
$id1 = IdGenerator::generate();
15+
$id2 = IdGenerator::generate();
16+
17+
static::assertNotSame($id1, $id2);
18+
static::assertSame(16, mb_strlen($id1));
19+
static::assertSame(16, mb_strlen($id2));
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace SoapTest\Psr18AttachmentsMiddleware\Unit\Encoding\Xop;
4+
5+
use Phpro\ResourceStream\Factory\MemoryStream;
6+
use PHPUnit\Framework\Attributes\Test;
7+
use PHPUnit\Framework\TestCase;
8+
use Soap\Encoding\Encoder\Context;
9+
use Soap\Encoding\EncoderRegistry;
10+
use Soap\Engine\Metadata\Collection\MethodCollection;
11+
use Soap\Engine\Metadata\Collection\TypeCollection;
12+
use Soap\Engine\Metadata\InMemoryMetadata;
13+
use Soap\Engine\Metadata\Model\XsdType;
14+
use Soap\Psr18AttachmentsMiddleware\Attachment\Attachment;
15+
use Soap\Psr18AttachmentsMiddleware\Encoding\Xop\XopIncludeEncoder;
16+
use Soap\Psr18AttachmentsMiddleware\Storage\AttachmentStorage;
17+
use Soap\Psr18AttachmentsMiddleware\Storage\AttachmentStorageInterface;
18+
use Soap\WsdlReader\Model\Definitions\Namespaces;
19+
20+
final class XopIncludeEncoderTest extends TestCase
21+
{
22+
#[Test]
23+
public function it_can_encode_xop_include_attachment(): void
24+
{
25+
$encoder = $this->createEncoder(
26+
$storage = $this->createStorage()
27+
);
28+
$iso = $encoder->iso($this->createContext());
29+
30+
$result = $iso->to(
31+
$attachment = new Attachment('foo', 'file', 'file.pdf', 'application/pdf', MemoryStream::create())
32+
);
33+
34+
static::assertSame('<xop:Include href="cid:foo" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>', $result);
35+
static::assertSame($attachment, $storage->requestAttachments()->findById('foo'));
36+
}
37+
38+
#[Test]
39+
public function it_can_decode_xop_include_attachment(): void
40+
{
41+
$encoder = $this->createEncoder(
42+
$storage = $this->createStorage()
43+
);
44+
$iso = $encoder->iso($this->createContext());
45+
46+
$storage->responseAttachments()->add(
47+
$attachment = new Attachment('foo', 'file', 'file.pdf', 'application/pdf', MemoryStream::create())
48+
);
49+
$result = $iso->from('<xop:Include href="cid:foo" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>');
50+
51+
static::assertSame($attachment, $result);
52+
}
53+
54+
private function createStorage(): AttachmentStorageInterface
55+
{
56+
return new AttachmentStorage();
57+
}
58+
59+
private function createEncoder(AttachmentStorageInterface $storage): XopIncludeEncoder
60+
{
61+
return new XopIncludeEncoder($storage);
62+
}
63+
64+
private function createContext(): Context
65+
{
66+
return new Context(
67+
XsdType::any(),
68+
new InMemoryMetadata(new TypeCollection(), new MethodCollection()),
69+
EncoderRegistry::default(),
70+
new Namespaces([], []),
71+
);
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace SoapTest\Psr18AttachmentsMiddleware\Unit\Exception;
4+
5+
use PHPUnit\Framework\Attributes\Test;
6+
use PHPUnit\Framework\TestCase;
7+
use Soap\Engine\Exception\RuntimeException;
8+
use Soap\Psr18AttachmentsMiddleware\Exception\AttachmentNotFoundException;
9+
10+
final class AttachmentNotFoundExceptionTest extends TestCase
11+
{
12+
#[Test]
13+
public function it_can_throw_by_id(): void
14+
{
15+
$exception = AttachmentNotFoundException::withId('foo');
16+
17+
$this->expectException(AttachmentNotFoundException::class);
18+
$this->expectException(RuntimeException::class);
19+
$this->expectExceptionMessage('Attachment with id "foo" can not be found.');
20+
throw $exception;
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace SoapTest\Psr18AttachmentsMiddleware\Unit\Exception;
4+
5+
use PHPUnit\Framework\Attributes\Test;
6+
use PHPUnit\Framework\TestCase;
7+
use Soap\Engine\Exception\RuntimeException;
8+
use Soap\Psr18AttachmentsMiddleware\Exception\SoapMessageNotFoundException;
9+
10+
final class SoapMessageNotFoundExceptionTest extends TestCase
11+
{
12+
#[Test]
13+
public function it_can_throw_from_multipart_context(): void
14+
{
15+
$exception = SoapMessageNotFoundException::insideMultipart('soapmessage', 'application/soap+xml');
16+
17+
$this->expectException(SoapMessageNotFoundException::class);
18+
$this->expectException(RuntimeException::class);
19+
$this->expectExceptionMessage('Soap message with id "soapmessage" and type "application/soap+xml" can not be found inside multipart response.');
20+
throw $exception;
21+
}
22+
23+
}

0 commit comments

Comments
 (0)