MagicSearch


Это общедоступный API-метод, который вы можете подергать для ознакомления.

Все методы сделаны для моего курса «Тестирование REST API». Теорию я выкладываю на youtube и в блог, а за практикой заходите!

ТЗ в гуглодоке — копируйте откуда удобно, из гуглодоки или конфлюенса.

Это пример метода из реальной жизни, с кучей условий и бизнес-логики. Именно после тестирования похожего метода в рельной системе я написала блог-пост «В тестировании всегда начинаем с простого!». Будьте внимательны в попытке сократить количество тестов!

Поиск по сотрудникам или компаниям

REST — http://users.bugred.ru/tasks/rest/magicsearch


Легенда

Менеджер ищет по пользователям, но его интересуют их задачи в том числе. Или он хочет посмотреть на сотрудников компании “Ромашка”, или сколько в этой компании невыполненных задач.

Заголовки

Заголовок

Описание

Content-Type

Тип данных в запросе: application/json, application/xml, form-data

Accept

Тип данных в ответе: application/json

Входные параметры

Имя параметра

Тип

Обязательный?

Описание

query

string

да

Критерии поиска.

partyType

Выбор:

  • USER
  • COMPANY

нет

Где искать: в юзерах или компаниях

fullSimilarity

boolean

нет

Искать только по полному совпадению (по умолчанию False)

taskStatus

Статус задачи

нет

Искать только тех, у кого есть задачи в таком статусе

include

Набор значений

нет

Дополнительная информация о контрагенте

maxCount

int

нет

Количество результатов, возвращаемых в ответе

Правила формирования раздела <query>

Можно искать по пользователю по полям:

  • фио,
  • емейл,
  • дата рождения,
  • имя1,
  • фамилия1,
  • отчество1,
  • телефон,
  • Адрес
  • ИНН

Можно по компаниям:

  • Название
  • ИНН
  • ОГРН
  • КПП
  • Адрес
  • Телефон

Запрос работает по условию «И». Если указано “Вася Пупкин”, это должен быть человек, у которого оба слова совпали с поисковым запросом.
Но можно поискать «Иванов Петушки» — вернется пользователь Иванов из компании Петушки.
Максимальная длина запроса — 1000 символов

Правила формирования раздела <partyType>

Если выбрано:

  • USER — ищем только среди пользователей
  • COMPANY — только среди компаний
  • Ничего не выбрано — среди тех и других

Если ничего не выбрано, по ИНН вернется и юзер, и компания. По «Иванов Петушки» вернется и сам Иванов, и Петушки.
А вот если выбрано USER, то по «Иванов Петушки» вернется только Иванов

Правила формирования раздела <fullSimilarity>

  • True — только полное совпадение слов из поиска
  • False — как сейчас, можно частичное

Пример: поиск по «Оля» найдет как ФИО “Оля”, так и ФИО “Оляля, Оляля, ляляляля” (false)
При флаге true — только «Оля».

Правила формирования раздела <taskStatus>

Узел <taskStatus> постоянен и содержит следующие части:

Значения параметра //taskStatus

Описание

ALL

Все статусы

ACTUAL

Текущие

COMPLETE

Выполненные

FAIL

Пропущенные

Если мы ищем среди компаний, то проверяются статусы задач по каждому сотруднику.
Если у сотрудника есть задача в таком статусе — вернем компанию и этого сотрудника, остальных сотрудников не вернем. Если у компании 5 сотрудников, но только 2 есть задачи в нужном статусе — вернем компанию и этих двух сотрудников.

Правила формирования раздела <include>

Узел <include> постоянен и содержит следующие части:

Значения параметра //include

Описание

ALL

Вся информация:

  • пользователь, его компании, его задачи + блок WHY
  • Компания, ее сотрудники, список задач внутри сотрудника + блок WHY

USER

Информация только о найденном пользователе / сотруднике компании

COMPANY

Информация только о компании

TASK

Информация только о задачах пользователя (от самого пользователя указывается email, чтобы различить разных)

WHY

Блок с информацией об атрибутах, в которых нашли совпадение

По умолчанию его можно не указывать в запросе, тогда в ответе вернутся все перечисленные блоки, кроме WHY.
Указать можно несколько значений (массив):

"include":["COMPANY","TASK"]

Если какой-то узел не выбран, но он есть — от него возвращается только шапка (см раздел «Выходные параметры» и примеры)

Если указан блок WHY, то в ответе добавляется информация, по чему именно мы нашли.
Например, в запросе было “Москва, Ленина”
В ответе добавляется блок

"why_block": [
{
"field": "adress",
"value": "Москва, Ленина"
}
],

Правила формирования раздела <maxCount>


В разделе <maxCount> передается количество записей, которые необходимо вернуть в ответе.
Если параметр <maxCount> в запросе не указан, то по умолчанию возвращается 5 записей по пользователем и 5 записей по компаниям с указанием общего количества найденных записей в параметре foundCount. Максимальное количество записей, которое возвращает метод – 30.
Сначала возвращаем юзеров, потом компании. Юзеры в порядке создания (по возрастанию, кто раньше создан, тот и актуальнее), компании по ИД (тоже по возрастанию)


Выходные параметры

Имя параметра

Тип

Описание

foundCount

int

Сколько найдено результатов поиска

results

Пользователь / Компания

Сами результаты

Пользователь

Если найден пользователь, вернуть:
— все поля пользователя. В заголовке (шапке) указывается емейл
— блок компаний, в которых он сотрудник. В заголовке указывается ИД
— блок задач, которые на нем висят. В заголовок выводится ИД и статус (статусы перечислены в разделе Include)
— why-блок (по какой информации нашли компанию)

Пример 1. Нашли и компанию, и пользователя

{
<!-- Мы можем найти и несколько пользователей, но тут найден один. Вначале всегда идет количество найденных -->
"foundCount": 1,

<!-- Пошла инфа о найденных результатах. Если найдено несколько пользователей, то закрыв тег одного user, открываем второй (фигурные скобки) -->
"results": [
{
"name": "Красавчик",
"email": "test2@gmail.com",
"date": "2018-08-15",
"avatar": "/tmp/default_avatar.jpg",
"by_user": "rest",
"name1": "Тестовый, ясен пень",
"hobby": "Стрельба из лука, Настолки",
"surname1": "Иванов",
"fathername1": "Петров",
"cat": "Маруся",
"dog": "Ушастый",
"parrot": "Васька",
"cavy": "Кто ты?",
"hamster": "Хомяк",
"squirrel": "Белая горячка к нам пришла",
"phone": "333 33 33",
"adres": "адрес 1",
"gender": "m",
"birthday": "01.01.1900",
"inn": "123456789012",
<!-- Блок задач, если они есть. От задачи нужно название, ИД и статус →
"tasks": [
{
"status": "ACTUAL",
"name": "Вторая задача",
"id_task": 103
},
{
"status": "ACTUAL",
"name": "Первая задача",
"id_task": 102
}
],

<!-- Блок компаний, если они есть. От компании нам нужно наименование и ИД.
Если в компании есть другие сотрудники, кроме найденного — нам ПЛЕВАТЬ! Мы берем только один уровень вложенности. Искали юзера — вернули компанию
→
"companies": [
{
"name": "ОАО Ромашка",
"id_company": 37
}
{
"name": "ОАО Петушки",
"id_company": 39
}
],
<!-- Информация о том, по каким данным пользователь был найден →
"why_block": [
{
"field": "email",
"value": "test_cu_360@mail.com"
}
],

<!-- Тип найденного результата — юзер →
"type": "user"
<!-- Все. Инфа по этому юзеру закончена, закрываем тег →
}
]
}

Пример 2. Нашли и компанию, и пользователя, но в запросе include = USER

Если взять тот же пример, но у нас было указано include = USER, то инфу по юзеру возвращаем полностью, а по компаниям и таскам — не возвращаем.
Если у пользователя заполнено мало полей — в ответе будут только они

{
"foundCount": 1,
"results": [
{
"name": "Рестовый 77",
"date": "2018-09-24",
"email": "test_cu_360@mail.com",
"by_user": "manager@mail.ru",
"type": "user"
}
]
}

Если include = USER, COMPANY — информация возвращается только по юзеру и компании

Компания

Если найдена компания, вернуть:
— все поля компании
— блок сотрудников (перечисление их email)
— why-блок (по какой информации нашли компанию)

Пример 3. Поиск по компании

Запрос

{
"query":"Ромашка"
}


Ответ

{
<!-- Найдена только 1 компания -->
"foundCount": 1,

<!-- Пошла инфа о найденных результатах -->
"results": [
{
<!-- Вот и наша Ромашка! -->
"name": "Ромашка",
"type": "company",
"inn": "1234567890",
"ogrn": "1234567890123",
"kpp": "123456799",
"phone": "678",
"adress": "новый",

<!-- Сотрудники компании -->
"users": [
"test_cu_11@mail.com",
"test_cu_6@mail.com",
"test_cu_5@mail.com",
"newsupermail1@noibiz.com",
"asdf@mail.ru",
"super2@super2.com"
],

<!-- По какому полю нашли -->
"why_block": [
{
"field": "name",
"value": "Ромашка"
}
],

<!-- ИД компании -->
"id_company": 7
}
]
}

Статусы ответов

Расширяем стандартный список — https://httpstatuses.com/, нам по бизнес-логике важно различать ситуации

  • 230 — никого не нашли по запросу, пустой ответ
  • 231 — найден 1 юзер
  • 232 — найдено больше 1 юзера (но без компаний)
  • 233 — найдена 1 компания
  • 234 — найдено больше 1 компании (но без юзеров)
  • 235 — найдены как юзеры, так и компании
  • 200 — запрос выполнен успешно и не попал под вышеизложенные сценарии (ну вдруг)

Ошибки на клиенте:

  • 455 — не указан параметр query в запросе. Body сообщения — “Не найден обязательный параметр query”
  • 456 — длина запроса выше 1000 символов. Текст ошибки — “Длина запроса не должна превышать 1000 символов”
  • 457 — неправильно задан partyType (значение не из доступного списка выбора). Текст ошибки — “Параметр partyType может принимать только значения: ALL, USER, COMPANY”
  • 458 — неправильно задан параметр taskStatus (не из списка выбора значение). Текст ошибки — “Параметр taskStatus может принимать только значения: ALL, ACTUAL, COMPLETE, FAIL”
  • 459 — неправильно задан параметр include (не из списка выбора значение). Текст ошибки — “Параметр include может принимать только значения: ALL, USER, COMPANY, TASK, WHY”
  • 400 — все остальные ошибки (плохо составлен json или xml итд)

Как в REST это выглядит — понятно, там отдельно заголовок, отдельно тело. В SOAP это может выглядеть так

<ns2:errorMessage>
<ns2:errorStatus>456</ns2:errorStatus>
<ns2:errorMessage>Длина запроса не должна превышать 1000 символов</ns2:errorMessage>
</ns2:errorMessage>