Первая фиксация

This commit is contained in:
RedHood 2020-10-03 00:11:19 +10:00
commit 252b261720
30 changed files with 11119 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/vendor

91
Mirzaev/Feip/Error.php Normal file
View File

@ -0,0 +1,91 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip;
/**
* Ошибка
*
* Сборщик ошибок
*
* @property string ERROR_100 Не установлен обязательный параметр
* @property string ERROR_200 Неподходящее значение параметра
* @property array $errors Собранные ошибки
*
* @method public function __construct(int $type, string $target = null, string $message = null) Создать ошибку
* @method public static function get(int $number = null) Получить одну, либо все ошибки
*
* @package Mirzaev\Feip\Error
* @author Арсен Мирзаев <red@hood.su>
*
* @todo Я бы вместо этого подключил библеотеку на PSR-7, да сделал там сбор и возврат всех ТИПОВ ошибок
*/
class Error
{
/**
* Ошибка #100
*
* Не установлен обязательный параметр
*
* @var string
*/
protected const ERROR_100 = 'Не установлен обязательный параметр';
/**
* Ошибка #200
*
* Неподходящее значение параметра
*
* @var string
*/
protected const ERROR_200 = 'Неподходящее значение параметра';
/**
* Ошибки
*
* Собранные ошибки за время выполнения
*
* @var array
*/
protected static array $errors = [];
/**
* Создать ошибку
*
* @param int $type Тип ошибки
* @param string|null $target Причина ошибки
* @param string|null $message Сообщение об ошибке
*
* @todo Я бы переименовал $type (Тип ошибки) в $code (Код ошибки), но уже поздно
*
* @return void
*/
public function __construct(int $type, string $target = null, string $message = null)
{
self::$errors[] = [
'type' => $type,
'target' => $target ?? 'request',
'value' => $message ?? constant('self::ERROR_' . $type)
];
}
/**
* Получить одну, либо все ошибки
*
* @param int|null $number Номер ошибки
*
* @return array
*/
public static function get(int $number = null): array
{
// Одна ошибка
if (isset($number)) {
// Если передан номер ошибки
return self::$errors[$number];
}
// Все ошибки
return self::$errors;
}
}

View File

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip\Methods;
use Mirzaev\Feip\Methods\MethodAbstract,
Mirzaev\Feip\Error,
Mirzaev\Feip\Params\Bar,
Mirzaev\Feip\Params\Email,
Mirzaev\Feip\Params\Users;
/**
* Foo
*
* @property string $bar bar
* @property string $email Почта
* @property array $users Пользователи
*
* @method public function __construct(array $params) Сборщик
* @method public filter(string $var, $params) Фильтрация входящих параметров
* @method public function json() Возвращает json-строку собранную из объекта
* @method private static function camelCase(string $text) Конвертация в camelCase (lower)
*
* @see Mirzaev\Feip\Tests\Bar
*
* @package Mirzaev\Feip\Methods\Bar
* @author Арсен Мирзаев <red@hood.su>
*/
class BarMethod extends MethodAbstract
{
use Bar, Email, Users;
}

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip\Methods;
use Mirzaev\Feip\Methods\MethodAbstract,
Mirzaev\Feip\Params\Foo,
Mirzaev\Feip\Params\Bar,
Mirzaev\Feip\Params\Baz;
/**
* Foo
*
* @property int $foo foo
* @property string $bar bar
* @property string $baz baz
*
* @method public function __construct(array $params) Сборщик
* @method public filter(string $var, $params) Фильтрация входящих параметров
* @method public function json() Возвращает json-строку собранную из объекта
* @method private static function camelCase(string $text) Конвертация в camelCase (lower)
*
* @see Mirzaev\Feip\Tests\Foo
*
* @package Mirzaev\Feip\Methods
* @author Арсен Мирзаев <red@hood.su>
*/
class FooMethod extends MethodAbstract
{
use Foo, Bar, Baz;
}

View File

@ -0,0 +1,182 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip\Methods;
use Mirzaev\Feip\Error;
/**
* MethodAbstract
*
* @param array $ignore Список игнорируемых свойств
*
* @method public function __construct(array $params) Сборщик
* @method public filter(string $var, $params) Фильтрация входящих параметров
* @method public function json() Возвращает json-строку собранную из объекта
* @method private static function camelCase(string $text) Конвертация в camelCase (lower)
*
* @package Mirzaev\Feip\Methods
* @author Арсен Мирзаев <red@hood.su>
*/
class MethodAbstract
{
/**
* Список игнорируемых свойств
*
* @var array
*/
protected array $ignore = [];
/**
* Сборщик
*
* Получает параметры и присваивает к одноимённым свойствам
*
* @param array $params Параметры
*/
public function __construct(array $params)
{
// Обработка входящих параметров
foreach ($this as $var => $value) {
// Перебор свойств объекта
// Вызов метода Before
$method = $this::camelCase($var . 'Before');
if (method_exists($this, $method)) {
// Если есть метод before, то вызвать его
$this::$method();
}
// Список игнорируемых параметров
if (in_array($var, $this->ignore) || $var === 'ignore') {
// Если найден в списке, то пропустить
continue;
}
// Нет значения
if (empty($params[$var])) {
// Если переданный параметр имеет пустое значение
new Error(100, $var);
continue;
}
// Массив
if (is_array($params[$var])) {
// Массив
if (is_array($value)) {
// Если тип идентичного параметру свойства является массивом
$this->$var = $this->filter($var, $params[$var]);
} else {
new Error(200, $var);
}
} else if (null !== $filtered = $this->filter($var, $params[$var])) {
// Иначе, если получено скалярное значение и результат его фильтрации
$this->$var = $filtered;
}
// Вызов метода After
$method = $this::camelCase($var . 'After');
if (method_exists($this, $method)) {
// Если есть метод after, то вызвать его
$this::$method();
}
}
}
/**
* Фильтр
*
* @param string|int $var Свойство объекта
* @param mixed $params Параметры
*
* @return mixed
*/
public function filter($var, $params)
{
// Инициализация
$response = [];
if (!is_array($params)) {
// Если передан скалярный параметр
$params = [$var => $params];
}
// Обработка
foreach ($params as $key => $value) {
// Перебор входных параметров
// Массив
if (is_array($value)) {
// Если передан массив, то войти в цикл для обработки
$response[$key] = $this->filter($key, $value);
}
// Инициализация метода
$method = $this::camelCase($key);
// Скалярное значение
if (method_exists($this, $method)) {
// Если существует фильтр для параметра
if ($value_filtered = $this::$method($value)) {
// Если фильтрация вернула результат
$response[$key] = $value_filtered;
}
}
}
// Деинициализация
if (count($params) === 1) {
// Если в начале был передан скалярный параметр
$response = array_pop($response);
}
return $response;
}
/**
* Конвертация в json
*
* Возвращает строку json со значеним из всех свойств объекта
*
* @return string
*/
public function json(): string
{
// Инициализация
$response = [
'response' => [],
'errors' => Error::get()
];
// Генерация ответа
foreach ($this as $var => $value) {
// Перебор свойств объекта
if (in_array($var, $this->ignore) || $var === 'ignore') {
// Если добавлен в чёрный список, то пропустить
continue;
}
$response['response'][$var] = $value;
}
var_dump($this->ignore);
return json_encode($response);
}
/**
* Конвертация в camelCase (lower)
*
* Возвращает строку в формате camelCase (lower)
*
* @param string|int $text Строка для конвертации
*
* @return string
*/
private static function camelCase($text): string
{
return (string) preg_replace_callback('/_(.?)/', fn ($m) => strtoupper($m[1]), $text);
}
}

View File

@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip\Params;
use Mirzaev\Feip\Error;
/**
* Параметр возраста
*
* @property int $age Возраст
*
* @package Mirzaev\Feip\Params
* @author Арсен Мирзаев <red@hood.su>
*/
trait Age
{
/**
* Возраст: параметр
*
* @var int
*/
protected int $age = 0;
/**
* Возраст: фильтр
*
* @param string|int|float $target Значение для фильтрации
*
* @return int|null
*/
public static function age($target): ?int
{
// Очистка
if ($sanitized = filter_var($target, FILTER_CALLBACK, array('options' => [self::class, 'onlyNumbers']))) {
// Если очищение вернуло результат
// Проверка
if ($sanitized !== (int) $target) {
// Если очищенное значение не совпадает с отправленным
new Error(200, __FUNCTION__);
} else if (filter_var($sanitized, FILTER_VALIDATE_INT) && $sanitized > 0 && $sanitized <= 150) {
return (int) $sanitized;
}
} else {
new Error(200, __FUNCTION__);
}
return null;
}
/**
* Возраст: очистка
*
* @param string|int|float $target Значение для очистки
*
* @return string|null
*/
public static function onlyNumbers($target): int
{
// Поиск цифр
preg_match_all('/[0-9]*/', $target, $match);
// Инициализация
$result = '';
// Конкатанация найденных цифр
foreach ($match[0] as $number) {
$result .= $number;
}
// В задании было сказано: для номеров тип string
return (int) $result;
}
}

View File

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip\Params;
use Mirzaev\Feip\Error;
/**
* Параметр bar
*
* @property string $bar bar
*
* @package Mirzaev\Feip\Params
* @author Арсен Мирзаев <red@hood.su>
*/
trait Bar
{
/**
* bar: параметр
*
* @var string
*/
protected string $bar = '';
/**
* bar: фильтр
*
* @param string|int|float $target Значение для фильтрации
*
* @return string|null
*/
public static function bar($target): ?string
{
// Очистка
if ($sanitized = filter_var($target, FILTER_SANITIZE_STRING)) {
// Если очищение вернуло результат
// Проверка
if ($sanitized !== $target) {
// Если очищенное значение не совпадает с отправленным
new Error(200, __FUNCTION__);
}
return (string) $sanitized;
} else {
new Error(200, __FUNCTION__);
}
return null;
}
}

View File

@ -0,0 +1,81 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip\Params;
use Mirzaev\Feip\Error;
/**
* Параметр baz
*
* @property string $baz baz
*
* @package Mirzaev\Feip\Params
* @author Арсен Мирзаев <red@hood.su>
*/
trait Baz
{
/**
* baz: параметр
*
* @var string
*/
protected string $baz = '';
/**
* baz: фильтр
*
* @param string|int|float $target Значение для фильтрации
*
* @return string|null
*/
public static function baz($target): ?string
{
// Очистка
if ($sanitized = filter_var($target, FILTER_CALLBACK, array('options' => [self::class, 'phoneNumberRus']))) {
// Если очищение вернуло результат
// Проверка
if ($sanitized !== $target || !preg_match('/^7[0-9]{10}$/', $sanitized)) {
// Если очищенное значение не совпадает с отправленным
// или если не совпадает с паттерном "7**********" (российский номер)
new Error(200, __FUNCTION__);
}
// В задании было указано: для номеров тип string
return (string) $sanitized;
} else {
new Error(200, __FUNCTION__);
}
return null;
}
/**
* baz: очистка
*
* @param string|int|float $target Значение для очистки
*
* @return string|null
*/
public static function phoneNumberRus($target): string
{
// Поиск цифр
preg_match_all('/[0-9]*/', $target, $match);
// Инициализация
$result = '';
// Конкатанация найденных цифр
foreach ($match[0] as $number) {
$result .= $number;
}
// Конвертация под Российский номер
$result[0] = 7;
// В задании было сказано: для номеров тип string
return (string) $result;
}
}

View File

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip\Params;
use Mirzaev\Feip\Error;
/**
* Параметр почты
*
* @property string $email Почта
*
* @package Mirzaev\Feip\Params
* @author Арсен Мирзаев <red@hood.su>
*/
trait Email
{
/**
* Почта: параметр
*
* @var string
*/
protected string $email = '';
/**
* Почта: фильтр
*
* @param string|int|float $target Значение для фильтрации
*
* @return string|null
*/
public static function email($target): ?string
{
// Очистка
if ($sanitized = filter_var($target, FILTER_SANITIZE_EMAIL)) {
// Если очищение вернуло результат
// Проверка
if ($sanitized !== $target || !preg_match("/[0-9A-z]+@[A-z]+\.[A-z]+/", $sanitized)) {
// Если очищенное значение не совпадает с отправленным
// или если не совпадает с паттерном "email"
new Error(200, __FUNCTION__);
}
return (string) $sanitized;
} else {
new Error(200, __FUNCTION__);
}
return null;
}
}

View File

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip\Params;
use Mirzaev\Feip\Error;
/**
* Параметр имени
*
* @property string $first_name Имя
*
* @package Mirzaev\Feip\Params
* @author Арсен Мирзаев <red@hood.su>
*/
trait FirstName
{
/**
* Имя: параметр
*
* @var string
*/
protected string $first_name = '';
/**
* Имя: фильтр
*
* @param mixed $target Значение для фильтрации
*
* @return array|null
*/
public static function firstName($target): ?array
{
// Очистка
if ($sanitized = filter_var($target, FILTER_SANITIZE_STRING)) {
// Если очищение вернуло результат
// Проверка
if ($sanitized !== $target) {
// Если очищенное значение не совпадает с отправленным
new Error(200, __FUNCTION__);
}
return (array) $sanitized;
} else {
new Error(200, __FUNCTION__);
}
return null;
}
}

View File

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip\Params;
use Mirzaev\Feip\Error;
/**
* Параметр foo
*
* @property int $foo foo
*
* @package Mirzaev\Params\Filters
* @author Арсен Мирзаев <red@hood.su>
*/
trait Foo
{
/**
* foo: параметр
*
* @var int
*/
protected int $foo = 0;
/**
* foo: фильтр
*
* @param string|int|float $target Значение для фильтрации
*
* @return int|null
*/
public static function foo($target): ?int
{
// Очистка
if ($sanitized = filter_var($target, FILTER_SANITIZE_NUMBER_INT)) {
// Если очищение вернуло результат
// Проверка
if ($sanitized !== $target || !filter_var($sanitized, FILTER_VALIDATE_INT)) {
// Если очищенное значение не совпадает с отправленным
// или если не прошло проверку FILTER_VALIDATE_INT (но её невозможно не пройти здесь, просто так добавил)
new Error(200, __FUNCTION__);
}
return (int) $sanitized;
} else {
new Error(200, __FUNCTION__);
}
return null;
}
}

View File

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip\Params;
use Mirzaev\Feip\Error;
/**
* Параметр фамилии
*
* @property string $second_name Фамилия
*
* @package Mirzaev\Feip\Params
* @author Арсен Мирзаев <red@hood.su>
*/
trait SecondName
{
/**
* Фамилия: параметр
*
* @var string
*/
protected string $second_name = '';
/**
* Фамилия: фильтр
*
* @param mixed $target Значение для фильтрации
*
* @return array|null
*/
public static function secondName($target): ?array
{
// Очистка
if ($sanitized = filter_var($target, FILTER_SANITIZE_STRING)) {
// Если очищение вернуло результат
// Проверка
if ($sanitized !== $target) {
// Если очищенное значение не совпадает с отправленным
new Error(200, __FUNCTION__);
}
return (array) $sanitized;
} else {
new Error(200, __FUNCTION__);
}
return null;
}
}

View File

@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
namespace Mirzaev\Feip\Params;
use Mirzaev\Feip\Error,
Mirzaev\Feip\Methods\MethodAbstract,
Mirzaev\Feip\Params\FirstName,
Mirzaev\Feip\Params\SecondName,
Mirzaev\Feip\Params\Age;
/**
* Параметр пользователей
*
* @property array $users Пользователи
*
* @package Mirzaev\Feip\Params
* @author Арсен Мирзаев <red@hood.su>
*/
trait Users
{
use FirstName, SecondName, Age;
/**
* Пользователи: параметр
*
* @var array
*/
protected array $users = [];
/**
* Before
*
* Вызывается перед обработкой
*
* @return void
*/
public function usersBefore(): void
{
$this->ignore[] = 'first_name';
$this->ignore[] = 'second_name';
$this->ignore[] = 'age';
}
/**
* After
*
* Вызывается после обработки
*
* @return void
*/
public function usersAfter(): void
{
}
}

View File

@ -0,0 +1,7 @@
actor: BarTester
modules:
enabled:
- \Helper\Foo
- REST:
url: http://feip.loc/api/bar
depends: PhpBrowser

View File

@ -0,0 +1,107 @@
<?php
class BarCest
{
public function tryPostJsonToFilter(BarTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"bar": "asd",
"email": "test@mail.ru",
"users": [
{
"first_name": "Arsen",
"second_name": "Mirzaev",
"age": "19"
}
]
}'
]
);
$I->seeResponseContains('{"response":{"bar":"asd","email":"test@mail.ru","users":{"first_name":["Arsen"],"second_name":["Mirzaev"],"age":19}},"errors":[]}');
}
public function tryPostJsonToFilterButUsersHasSecond(BarTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"bar": "asd",
"email": "test@mail.ru",
"users": [
{
"first_name": "Arsen",
"second_name": "Mirzaev",
"age": "19"
},
{
"first_name": "Ivan",
"second_name": "Voronkov",
"age": "18"
}
]
}'
]
);
$I->seeResponseContains('{"response":{"bar":"asd","email":"test@mail.ru","users":[{"first_name":["Arsen"],"second_name":["Mirzaev"],"age":19},{"first_name":["Ivan"],"second_name":["Voronkov"],"age":18}]},"errors":[]}');
}
public function tryPostJsonToFilterButBarIsArray(BarTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"bar": [
{
"first_name": "Arsen",
"second_name": "Mirzaev",
"age": "19"
}
],
"email": "test@mail.ru",
"users": [
{
"first_name": "Arsen",
"second_name": "Mirzaev",
"age": "19"
}
]
}'
]
);
$I->seeResponseContains('{"response":{"bar":"","email":"test@mail.ru","users":{"first_name":["Arsen"],"second_name":["Mirzaev"],"age":19}},"errors":[{"type":200,"target":"bar","value":"\u041d\u0435\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430"}]}');
}
public function tryPostJsonToFilterButEmailHasWrongValue(BarTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"bar": "asd",
"email": "test@mail",
"users": [
{
"first_name": "Arsen",
"second_name": "Mirzaev",
"age": "19"
}
]
}'
]
);
$I->seeResponseContains('{"response":{"bar":"asd","email":"test@mail","users":{"first_name":["Arsen"],"second_name":["Mirzaev"],"age":19}},"errors":[{"type":200,"target":"email","value":"\u041d\u0435\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430"}]}');
}
}

View File

@ -0,0 +1,7 @@
actor: FooTester
modules:
enabled:
- \Helper\Foo
- REST:
url: http://feip.loc/api/foo
depends: PhpBrowser

View File

@ -0,0 +1,191 @@
<?php
class FooCest
{
public function tryPostJsonToFilter(FooTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"foo": "123",
"bar": "asd",
"baz": "79502885623"
}'
]
);
$I->seeResponseContains('{"response":{"foo":123,"bar":"asd","baz":"79502885623"},"errors":[]}');
}
public function tryPostJsonToFilterButFooIsEmpty(FooTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"foo": "",
"bar": "asd",
"baz": "79502885623"
}'
]
);
$I->seeResponseContains('{"response":{"foo":0,"bar":"asd","baz":"79502885623"},"errors":[{"type":100,"target":"foo","value":"\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440"}]}');
}
public function tryPostJsonToFilterButFooHasWrongValue(FooTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"foo": "123абв",
"bar": "asd",
"baz": "79502885623"
}'
]
);
$I->seeResponseContains('{"response":{"foo":123,"bar":"asd","baz":"79502885623"},"errors":[{"type":200,"target":"foo","value":"\u041d\u0435\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430"}]}');
}
public function tryPostJsonToFilterButFooWithoutValue(FooTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"bar": "asd",
"baz": "79502885623"
}'
]
);
$I->seeResponseContains('{"response":{"foo":0,"bar":"asd","baz":"79502885623"},"errors":[{"type":100,"target":"foo","value":"\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440"}]}');
}
public function tryPostJsonToFilterButBarIsEmpty(FooTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"foo": "123",
"bar": "",
"baz": "79502885623"
}'
]
);
$I->seeResponseContains('{"response":{"foo":123,"bar":"","baz":"79502885623"},"errors":[{"type":100,"target":"bar","value":"\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440"}]}');
}
public function tryPostJsonToFilterButBarWithoutValue(FooTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"foo": "123",
"baz": "79502885623"
}'
]
);
$I->seeResponseContains('{"response":{"foo":123,"bar":"","baz":"79502885623"},"errors":[{"type":100,"target":"bar","value":"\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440"}]}');
}
public function tryPostJsonToFilterButBazIsEmpty(FooTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"foo": "123",
"bar": "asd",
"baz": ""
}'
]
);
$I->seeResponseContains('{"response":{"foo":123,"bar":"asd","baz":""},"errors":[{"type":100,"target":"baz","value":"\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440"}]}');
}
public function tryPostJsonToFilterButBazHasWrongValue(FooTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"foo": "123",
"bar": "asd",
"baz": "8 (950) 288-56-23"
}'
]
);
$I->seeResponseContains('{"response":{"foo":123,"bar":"asd","baz":"79502885623"},"errors":[{"type":200,"target":"baz","value":"\u041d\u0435\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430"}]}');
}
public function tryPostJsonToFilterButBazHasTooShortValue(FooTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"foo": "123",
"bar": "asd",
"baz": "260557"
}'
]
);
$I->seeResponseContains('{"response":{"foo":123,"bar":"asd","baz":"760557"},"errors":[{"type":200,"target":"baz","value":"\u041d\u0435\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430"}]}');
}
public function tryPostJsonToFilterButBazWithoutValue(FooTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"foo": "123",
"bar": "asd"
}'
]
);
$I->seeResponseContains('{"response":{"foo":123,"bar":"asd","baz":""},"errors":[{"type":100,"target":"baz","value":"\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440"}]}');
}
public function tryPostJsonToFilterButBarIsArray(FooTester $I)
{
$I->haveHttpHeader('User-Agent', 'FEIP Tester');
$I->haveHttpHeader('Content-Type', 'application/x-www-form-urlencoded');
$I->sendPOST(
'/index.php',
[
'{
"foo": "123",
"bar": {
"bar_foo": "100",
"bar_bar": "sad"
},
"baz": "79502885623"
}'
]
);
$I->seeResponseContains('{"response":{"foo":123,"bar":"","baz":"79502885623"},"errors":[{"type":200,"target":"bar","value":"\u041d\u0435\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430"}]}');
}
}

View File

1
Mirzaev/Feip/Tests/_output/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
./*

View File

View File

@ -0,0 +1,26 @@
<?php
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method void pause()
*
* @SuppressWarnings(PHPMD)
*/
class BarTester extends \Codeception\Actor
{
use _generated\BarTesterActions;
/**
* Define custom actions here
*/
}

View File

@ -0,0 +1,26 @@
<?php
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method void pause()
*
* @SuppressWarnings(PHPMD)
*/
class FooTester extends \Codeception\Actor
{
use _generated\FooTesterActions;
/**
* Define custom actions here
*/
}

View File

@ -0,0 +1,10 @@
<?php
namespace Helper;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
class Bar extends \Codeception\Module
{
}

View File

@ -0,0 +1,10 @@
<?php
namespace Helper;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
class Foo extends \Codeception\Module
{
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

29
README.md Normal file
View File

@ -0,0 +1,29 @@
```php
declare(strict_types=1);
use Dotenv\Dotenv;
use VK\Core as VK;
use VK\API\Methods\Message;
// Подключение зависимостей и настроек
require_once './vendor/autoload.php';
Dotenv::createImmutable(__DIR__)->load();
/**
* Инициализация и настрйока ядра
*
* @return object Экземпляр класса ядра
**/
VK::init()->log();
/**
* Сборка робота из ядра фреймворка
*
* @return int Идентификатор робота (0)
**/
VK::init()->build()->robot();
// Отправка сообщения (ID робота, кому, сообщение)
Message::post(0, 214547089, 'Робот роботает!!!', 1);
```

9
codeception.yml Normal file
View File

@ -0,0 +1,9 @@
paths:
tests: Mirzaev/Feip/Tests
output: Mirzaev/Feip/Tests/_output
data: Mirzaev/Feip/Tests/_data
support: Mirzaev/Feip/Tests/_support
settings:
shuffle: false
lint: true

28
composer.json Normal file
View File

@ -0,0 +1,28 @@
{
"name": "mirzaev/feip",
"description": "FEIP test project: \"sanitizer\"",
"type": "project",
"license": "AGPL-3.0-or-later",
"authors": [
{
"name": "Arsen Mirzaev",
"email": "red@hood.su",
"role": "Developer"
}
],
"require": {
"php": ">=7.4.0"
},
"require-dev": {
"phpdocumentor/phpdocumentor": ">=2.9",
"codeception/codeception": "^4.1",
"codeception/module-asserts": "^1.0.0",
"codeception/module-phpbrowser": "^1.0",
"codeception/module-rest": "^1.0.0"
},
"autoload": {
"psr-4": {
"Mirzaev\\Feip\\": "Mirzaev/Feip"
}
}
}

5890
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff