221 lines
5.9 KiB
PHP
221 lines
5.9 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Softra API smoke test:
|
|
* 1) reads credentials from .env (format: "key: value")
|
|
* 2) authenticates (/account/auth)
|
|
* 3) fetches branches (/branch/list)
|
|
* 4) fetches car models (/car/model/list?includeBrandDetails=true)
|
|
*
|
|
* Usage:
|
|
* php softra-test.php
|
|
* php softra-test.php branch=BYDGOSZCZ from=2026-03-30T12:00:00 to=2026-04-02T12:00:00 category=
|
|
*/
|
|
|
|
function fail(string $message, int $code = 1): never
|
|
{
|
|
if (PHP_SAPI !== 'cli') {
|
|
http_response_code(500);
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
echo json_encode(['ok' => false, 'error' => $message], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
|
|
exit($code);
|
|
}
|
|
|
|
if (defined('STDERR')) {
|
|
fwrite(STDERR, $message . PHP_EOL);
|
|
} else {
|
|
echo $message . PHP_EOL;
|
|
}
|
|
exit($code);
|
|
}
|
|
|
|
function parseEnvFile(string $path): array
|
|
{
|
|
if (!is_file($path)) {
|
|
fail("Brak pliku .env: {$path}");
|
|
}
|
|
|
|
$result = [];
|
|
$lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
if ($lines === false) {
|
|
fail("Nie mogę odczytać pliku .env");
|
|
}
|
|
|
|
foreach ($lines as $line) {
|
|
$line = trim($line);
|
|
if ($line === '' || str_starts_with($line, '#')) {
|
|
continue;
|
|
}
|
|
|
|
// supports:
|
|
// key: value
|
|
// key=value
|
|
$sepPos = strpos($line, ':');
|
|
if ($sepPos === false) {
|
|
$sepPos = strpos($line, '=');
|
|
}
|
|
if ($sepPos === false) {
|
|
continue;
|
|
}
|
|
|
|
$key = trim(substr($line, 0, $sepPos));
|
|
$value = trim(substr($line, $sepPos + 1));
|
|
$value = trim($value, "\"'");
|
|
if ($key !== '') {
|
|
$result[strtolower($key)] = $value;
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
function parseInputArgs(?array $argv = null): array
|
|
{
|
|
$args = [];
|
|
|
|
if (PHP_SAPI === 'cli') {
|
|
$argv = $argv ?? [];
|
|
foreach (array_slice($argv, 1) as $arg) {
|
|
$pos = strpos($arg, '=');
|
|
if ($pos === false) {
|
|
continue;
|
|
}
|
|
$k = strtolower(trim(substr($arg, 0, $pos)));
|
|
$v = trim(substr($arg, $pos + 1));
|
|
$args[$k] = $v;
|
|
}
|
|
return $args;
|
|
}
|
|
|
|
foreach ($_GET as $k => $v) {
|
|
if (!is_string($k)) {
|
|
continue;
|
|
}
|
|
$args[strtolower($k)] = is_string($v) ? trim($v) : '';
|
|
}
|
|
|
|
return $args;
|
|
}
|
|
|
|
function requestJson(string $method, string $url, ?array $payload = null, array $headers = []): array
|
|
{
|
|
$ch = curl_init($url);
|
|
if ($ch === false) {
|
|
fail('Nie udało się zainicjować cURL');
|
|
}
|
|
|
|
$httpHeaders = array_merge(['Accept: application/json'], $headers);
|
|
if ($payload !== null) {
|
|
$httpHeaders[] = 'Content-Type: application/json';
|
|
}
|
|
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_CUSTOMREQUEST => strtoupper($method),
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_HTTPHEADER => $httpHeaders,
|
|
CURLOPT_TIMEOUT => 30,
|
|
CURLOPT_CONNECTTIMEOUT => 15,
|
|
]);
|
|
|
|
if ($payload !== null) {
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
|
}
|
|
|
|
$raw = curl_exec($ch);
|
|
$err = curl_error($ch);
|
|
$status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($raw === false) {
|
|
fail("Błąd połączenia cURL: {$err}");
|
|
}
|
|
|
|
$decoded = json_decode($raw, true);
|
|
if (!is_array($decoded)) {
|
|
$decoded = ['raw' => $raw];
|
|
}
|
|
|
|
return [
|
|
'status' => $status,
|
|
'body' => $decoded,
|
|
'raw' => $raw,
|
|
];
|
|
}
|
|
|
|
$env = parseEnvFile(__DIR__ . DIRECTORY_SEPARATOR . '.env');
|
|
$args = parseInputArgs($argv ?? null);
|
|
|
|
$baseUrl = rtrim($env['url'] ?? '', '/');
|
|
$username = $env['username'] ?? '';
|
|
$password = $env['password'] ?? '';
|
|
|
|
if ($baseUrl === '' || $username === '' || $password === '') {
|
|
fail('W .env muszą być pola: url, username, password');
|
|
}
|
|
|
|
$authRes = requestJson('POST', $baseUrl . '/account/auth', [
|
|
'login' => $username,
|
|
'password' => $password,
|
|
]);
|
|
|
|
if ($authRes['status'] !== 200 || empty($authRes['body']['token'])) {
|
|
fail("Auth nieudany (HTTP {$authRes['status']}): {$authRes['raw']}");
|
|
}
|
|
|
|
$token = (string) $authRes['body']['token'];
|
|
$authHeader = ['Authorization: Bearer ' . $token];
|
|
|
|
$branchesRes = requestJson('GET', $baseUrl . '/branch/list', null, $authHeader);
|
|
if ($branchesRes['status'] !== 200 || !is_array($branchesRes['body'])) {
|
|
fail("Pobranie oddziałów nieudane (HTTP {$branchesRes['status']}): {$branchesRes['raw']}");
|
|
}
|
|
|
|
$branches = $branchesRes['body'];
|
|
if (count($branches) === 0) {
|
|
fail('API działa, ale /branch/list zwróciło pustą listę oddziałów');
|
|
}
|
|
|
|
$branch = $args['branch'] ?? ($branches[0]['relatedBranchName'] ?? $branches[0]['name'] ?? '');
|
|
if ($branch === '') {
|
|
fail('Nie udało się ustalić branchName (podaj ręcznie: branch=NAZWA)');
|
|
}
|
|
|
|
$from = $args['from'] ?? (new DateTimeImmutable('+7 days'))->format('Y-m-d\TH:i:s');
|
|
$to = $args['to'] ?? (new DateTimeImmutable('+10 days'))->format('Y-m-d\TH:i:s');
|
|
$category = $args['category'] ?? ''; // empty = all categories
|
|
|
|
$modelsRes = requestJson(
|
|
'POST',
|
|
$baseUrl . '/car/model/list?includeBrandDetails=true',
|
|
[
|
|
'dateFrom' => $from,
|
|
'dateTo' => $to,
|
|
'branchName' => $branch,
|
|
'category' => $category,
|
|
],
|
|
$authHeader
|
|
);
|
|
|
|
if ($modelsRes['status'] !== 200 || !is_array($modelsRes['body'])) {
|
|
fail("Pobranie listy aut nieudane (HTTP {$modelsRes['status']}): {$modelsRes['raw']}");
|
|
}
|
|
|
|
$models = $modelsRes['body'];
|
|
|
|
$result = [
|
|
'ok' => true,
|
|
'baseUrl' => $baseUrl,
|
|
'branch' => $branch,
|
|
'dateFrom' => $from,
|
|
'dateTo' => $to,
|
|
'modelsCount' => count($models),
|
|
'models' => $models,
|
|
];
|
|
|
|
if (PHP_SAPI !== 'cli') {
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
}
|
|
|
|
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
|