diff --git a/.gitignore b/.gitignore index a9bb9c9..0e3b7e4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ composer.lock /tests/**/output/ tests/src/E2E/account.ini coverage.html +/tests/src/E2E/test.http diff --git a/composer.json b/composer.json index 41d794a..6c73aac 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,8 @@ "nette/tester": "^2.4", "phpstan/phpstan": "^1.8", "phpstan/phpstan-strict-rules": "^1.4", + "strictphp/http-clients": "^0.1.3", + "symfony/http-client": "^7.1", "tracy/tracy": "^2.9" }, "autoload": { diff --git a/src/Utils/FioRequestFactory.php b/src/Utils/FioRequestFactory.php index 61d696d..88c736b 100644 --- a/src/Utils/FioRequestFactory.php +++ b/src/Utils/FioRequestFactory.php @@ -43,14 +43,17 @@ public function post(string $uri, array $params, string $content): RequestInterf ); } - return $request->withBody($this->createMultiPart($filename, $stream, $params)); + $multipart = $this->createMultiPart($filename, $stream, $params); + + return $request->withHeader('Content-Type', 'multipart/form-data; boundary=' . $multipart->getBoundary()) + ->withBody($multipart); } /** * @param array{token: string, type: string, lng?: string} $params */ - protected function createMultiPart(string $filename, StreamInterface $file, array $params): StreamInterface + private function createMultiPart(string $filename, StreamInterface $file, array $params): MultipartStream { $newPost = [ [ diff --git a/tests/src/E2E/FioTest.php b/tests/src/E2E/FioTest.php index 8e02f8c..d144fb5 100644 --- a/tests/src/E2E/FioTest.php +++ b/tests/src/E2E/FioTest.php @@ -2,7 +2,27 @@ namespace h4kuna\Fio\Tests\E2E; +use GuzzleHttp\Psr7\HttpFactory; +use h4kuna\Dir\Dir; use h4kuna\Fio; +use Psr\Http\Client\ClientInterface; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; +use StrictPhp\HttpClients\Actions\FindExtensionFromHeadersAction; +use StrictPhp\HttpClients\Actions\StreamAction; +use StrictPhp\HttpClients\Clients\Event\Actions\MakePathAction; +use StrictPhp\HttpClients\Clients\Event\Entities\FileInfoEntity; +use StrictPhp\HttpClients\Clients\Event\Entities\HttpStateEntity; +use StrictPhp\HttpClients\Clients\Event\Events\FailedRequestEvent; +use StrictPhp\HttpClients\Clients\Event\Events\SuccessRequestEvent; +use StrictPhp\HttpClients\Contracts\ConfigContract; +use StrictPhp\HttpClients\Filesystem\Contracts\FileContract; +use StrictPhp\HttpClients\Filesystem\Contracts\FileFactoryContract; +use StrictPhp\HttpClients\Filesystem\Wrappers\File; +use StrictPhp\HttpClients\Managers\ConfigManager; +use StrictPhp\HttpClients\Requests\SaveForPhpstormRequest; +use StrictPhp\HttpClients\Responses\SaveResponse; +use Symfony\Component\HttpClient\Psr18Client; use Tester; require __DIR__ . '/../bootstrap.php'; @@ -17,13 +37,91 @@ if ($accounts === false) { throw new Fio\Exceptions\InvalidState('You have bad format for ini file. Let\'s see account.example.ini.'); } +$dir = new Dir(__DIR__ . '/../../temp'); -$fioFactory = new Fio\FioFactory($accounts); + +class Filesystem implements FileFactoryContract +{ + public function __construct( + private Dir $dir + ) { + } + + public function create(FileInfoEntity $file, string $suffix = ''): FileContract + { + $dir = $this->dir->dir($file->path); + \Nette\Utils\FileSystem::createDir($dir->getDir()); + + return new File($dir->filename($file->name . $suffix)); + } + +} + +class StoreConfig implements ConfigContract +{ + public function __construct(public bool $enabled = false) + { + } + + public function initFromDefaultConfig(ConfigContract $object): void + { + // TODO: Implement initFromDefaultConfig() method. + } + +} + +final class StoreResponseClient implements ClientInterface +{ + public function __construct( + private SaveForPhpstormRequest $saveForPhpstormRequest, + private ConfigManager $configManager, + private ClientInterface $client, + ) { + } + + public function sendRequest(RequestInterface $request): ResponseInterface + { + $config = $this->configManager->get(StoreConfig::class, $request->getUri()->getHost()); + + if ($config->enabled === false) { + return $this->client->sendRequest($request); + } + + $state = new HttpStateEntity($request); + try { + $response = $this->client->sendRequest($request); + } catch (\Throwable $e) { + $failed = new FailedRequestEvent($state->finish(), $e); + $this->saveForPhpstormRequest->save($failed); + throw $e; + } + + $success = new SuccessRequestEvent($state->finish(), $response); + $this->saveForPhpstormRequest->save($success, $response); + + return $response; + } + +} + +$psrFactory = new HttpFactory(); +$fioRequest = new Fio\Utils\FioRequestFactory($psrFactory, $psrFactory); +$psrClient = new Psr18Client(responseFactory: $psrFactory, streamFactory: $psrFactory); // symfony +// $psrClient = new Client(); // guzzle +$configManager = new ConfigManager(); +$configManager->addDefault(new StoreConfig(true)); +$filesystemFactory = new Filesystem($dir); +$makePathAction = new MakePathAction(); +$streamAction = new StreamAction(); +$saveResponse = new SaveResponse($filesystemFactory, $makePathAction, new FindExtensionFromHeadersAction(), $streamAction, serialized: false); +$saveForPhpstormRequest = new SaveForPhpstormRequest($filesystemFactory, $makePathAction, $saveResponse, $streamAction); +$client = new StoreResponseClient($saveForPhpstormRequest, $configManager, $psrClient); + +$fioFactory = new Fio\FioFactory($accounts, $dir->dir('fio'), client: $client, fioRequestFactory: $fioRequest); $fioRead = $fioFactory->createFioRead(); Tester\Assert::same($accounts['my-fio-account']['account'], $fioRead->getAccount()->getAccount()); -$movements = $fioRead->movements('2023-09-15', '2023-09-21'); -Tester\Assert::same(5, count($movements)); +$movements = $fioRead->movements('-14 days'); Tester\Assert::type(\stdClass::class, $movements->getInfo()); Tester\Assert::same($accounts['my-fio-account']['account'], $movements->getInfo()->accountId);