Этот документ описывает полный цикл тестирования API для проверки функциональности управления пользователями, ролями, roadmap, feature и task.
- Запущены Docker контейнеры с PostgreSQL и Redis
- Запущен бэкенд приложения
- База данных пустая (миграции выполняются автоматически при старте)
cd /qs/projector
docker compose down -vdocker compose up -d postgres redisПроверить статус:
docker compose pscd backend
./gradlew bootRunПроверить здоровье приложения:
curl -s http://localhost:8080/actuator/healthОжидаемый ответ: {"status":"UP"}
curl -s -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin","password":"admin"}' \
-c /tmp/cookies.txt -D /tmp/headers.txtПроверить наличие Set-Cookie заголовка с токеном X-Auth.
Сначала получить токен:
TOKEN=$(grep -i "set-cookie" /tmp/headers.txt | grep -o 'X-Auth=[^;]*' | cut -d= -f2)Создать роль:
curl -s -X POST http://localhost:8080/api/roles \
-H "Content-Type: application/json" \
-b "X-Auth=$TOKEN" \
-d '{"name":"TEST_ROLE","authorities":["USER_VIEW","ROLE_VIEW"]}' | jq .Ожидаемый ответ: JSON с полями id, name, authorities.
Проверить список ролей:
curl -s -X GET http://localhost:8080/api/roles -b "X-Auth=$TOKEN" | jq .Создать пользователя:
curl -s -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-b "X-Auth=$TOKEN" \
-d '{"email":"testuser@example.com","password":"testpass123"}' | jq .Ожидаемый ответ: JSON с полями id, email (без password и passHash).
Проверить список пользователей:
curl -s -X GET http://localhost:8080/api/users -b "X-Auth=$TOKEN" | jq .Получить ID текущего пользователя (admin):
ADMIN_ID=$(curl -s -X GET http://localhost:8080/api/users -b "X-Auth=$TOKEN" | jq '.[] | select(.email=="admin") | .id')Создать roadmap:
curl -s -X POST http://localhost:8080/api/roadmaps \
-H "Content-Type: application/json" \
-b "X-Auth=$TOKEN" \
-d "{\"projectName\":\"Test Project\",\"authorId\":$ADMIN_ID,\"mission\":\"Build amazing software\",\"description\":\"Test roadmap description\",\"participantIds\":[$ADMIN_ID]}" | jq .Ожидаемый ответ: JSON с полями id, projectName, authorId, mission, description, participantIds.
Проверить список roadmaps:
curl -s -X GET http://localhost:8080/api/roadmaps -b "X-Auth=$TOKEN" | jq .Сохранить ID созданного roadmap:
ROADMAP_ID=$(curl -s -X GET http://localhost:8080/api/roadmaps -b "X-Auth=$TOKEN" | jq '.[] | select(.projectName=="Test Project") | .id')Создать feature:
curl -s -X POST http://localhost:8080/api/features \
-H "Content-Type: application/json" \
-b "X-Auth=$TOKEN" \
-d "{\"year\":2024,\"quarter\":\"Q1\",\"authorId\":$ADMIN_ID,\"sprint\":1,\"release\":\"v1.0.0\",\"summary\":\"User authentication feature\",\"description\":\"Implement user login and registration\"}" | jq .Ожидаемый ответ: JSON с полями id, year, quarter, authorId, sprint, release, summary, description.
Проверить список features:
curl -s -X GET http://localhost:8080/api/features -b "X-Auth=$TOKEN" | jq .Сохранить ID созданной feature:
FEATURE_ID=$(curl -s -X GET http://localhost:8080/api/features -b "X-Auth=$TOKEN" | jq '.[] | select(.summary=="User authentication feature") | .id')Создать task:
curl -s -X POST http://localhost:8080/api/tasks \
-H "Content-Type: application/json" \
-b "X-Auth=$TOKEN" \
-d "{\"featureId\":$FEATURE_ID,\"authorId\":$ADMIN_ID,\"summary\":\"Implement login endpoint\",\"description\":\"Create REST API endpoint for user login\"}" | jq .Ожидаемый ответ: JSON с полями id, featureId, authorId, summary, description.
Проверить список tasks:
curl -s -X GET http://localhost:8080/api/tasks -b "X-Auth=$TOKEN" | jq .Сохранить ID созданной task:
TASK_ID=$(curl -s -X GET http://localhost:8080/api/tasks -b "X-Auth=$TOKEN" | jq '.[] | select(.summary=="Implement login endpoint") | .id')Получить ID созданной роли и ID пользователя:
USER_ID=$(curl -s -X GET http://localhost:8080/api/users -b "X-Auth=$TOKEN" | jq '.[] | select(.email=="testuser@example.com") | .id')
ROLE_ID=$(curl -s -X GET http://localhost:8080/api/roles -b "X-Auth=$TOKEN" | jq '.[] | select(.name=="TEST_ROLE") | .id')Назначить роль через обновление пользователя:
curl -s -X PUT http://localhost:8080/api/users/$USER_ID \
-H "Content-Type: application/json" \
-b "X-Auth=$TOKEN" \
-d "{\"email\":\"testuser@example.com\",\"roleIds\":[$ROLE_ID]}" | jq .Альтернативно, можно назначить роль напрямую в БД:
PGPASSWORD=projector psql -h localhost -p 5433 -U projector -d projector \
-c "INSERT INTO user_roles (user_id, role_id) VALUES ($USER_ID, $ROLE_ID) ON CONFLICT DO NOTHING;"Проверить в БД:
PGPASSWORD=projector psql -h localhost -p 5433 -U projector -d projector \
-c "SELECT user_id, role_id FROM user_roles WHERE user_id = $USER_ID;"curl -s -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"testuser@example.com","password":"testpass123"}' \
-D /tmp/login_headers.txtПроверить Set-Cookie заголовок:
grep -i "set-cookie" /tmp/login_headers.txtДекодировать JWT токен и проверить, что в authorities присутствуют права из назначенной роли (USER_VIEW, ROLE_VIEW).
Удалить task:
curl -s -X DELETE http://localhost:8080/api/tasks/$TASK_ID \
-b "X-Auth=$TOKEN" -w "\nHTTP:%{http_code}\n"Ожидаемый код: 204 No Content
Удалить feature:
curl -s -X DELETE http://localhost:8080/api/features/$FEATURE_ID \
-b "X-Auth=$TOKEN" -w "\nHTTP:%{http_code}\n"Ожидаемый код: 204 No Content
Удалить roadmap:
curl -s -X DELETE http://localhost:8080/api/roadmaps/$ROADMAP_ID \
-b "X-Auth=$TOKEN" -w "\nHTTP:%{http_code}\n"Ожидаемый код: 204 No Content
Получить ID созданного пользователя (например, 12) и роли (например, 11):
USER_ID=$(curl -s -X GET http://localhost:8080/api/users -b "X-Auth=$TOKEN" | jq '.[] | select(.email=="testuser@example.com") | .id')
ROLE_ID=$(curl -s -X GET http://localhost:8080/api/roles -b "X-Auth=$TOKEN" | jq '.[] | select(.name=="TEST_ROLE") | .id')Удалить пользователя:
curl -s -X DELETE http://localhost:8080/api/users/$USER_ID \
-b "X-Auth=$TOKEN" -w "\nHTTP:%{http_code}\n"Ожидаемый код: 204 No Content
Удалить роль:
curl -s -X DELETE http://localhost:8080/api/roles/$ROLE_ID \
-b "X-Auth=$TOKEN" -w "\nHTTP:%{http_code}\n"Ожидаемый код: 204 No Content
Проверить удаление в БД:
PGPASSWORD=projector psql -h localhost -p 5433 -U projector -d projector \
-c "SELECT id, email FROM users WHERE id = $USER_ID;"
PGPASSWORD=projector psql -h localhost -p 5433 -U projector -d projector \
-c "SELECT id, name FROM roles WHERE id = $ROLE_ID;"
PGPASSWORD=projector psql -h localhost -p 5433 -U projector -d projector \
-c "SELECT id, project_name FROM roadmaps WHERE id = $ROADMAP_ID;"
PGPASSWORD=projector psql -h localhost -p 5433 -U projector -d projector \
-c "SELECT id, summary FROM features WHERE id = $FEATURE_ID;"
PGPASSWORD=projector psql -h localhost -p 5433 -U projector -d projector \
-c "SELECT id, summary FROM tasks WHERE id = $TASK_ID;"Ожидаемый результат: пустые результаты (0 rows).
- Все запросы к защищенным эндпоинтам требуют аутентификации через cookie X-Auth
- Поле
passwordиспользуется только при создании/обновлении пользователя и никогда не возвращается в ответах - Поле
passHashявляется внутренним и никогда не возвращается клиенту - При создании пользователя поле
passwordобязательно - При обновлении пользователя: если
passwordне пустой - он хешируется и обновляется, иначе используется старый пароль из БД - При создании roadmap обязательны поля:
projectName,authorId - При создании feature обязательны поля:
year(2000-2500),quarter(Q1/Q2/Q3/Q4),authorId - При создании task обязательны поля:
featureId,authorId - Поля
createDateиupdateDateустанавливаются автоматически при создании/обновлении объектов