Бэкенд
Работа отклоняется от проверки
- API не регистрирует пользователя по валидным данным.
- Приложение не запускается с помощью команды npm run dev после установки всех необходимых зависимостей.
Критерии, влияющие на работоспособность
-
- в проекте есть package.json;
- .editorconfig;
- .eslintrc, расширяющий конфигурацию airbnb-base, а также необходимые для работы линтера dev-зависимости;
- .gitignore;
- в .eslintrc добавлено исключение для _id. Директивы eslint-disable, eslint-disable-line и eslint-disable-next-line запрещены.
- Нет ошибок линтера. При выполнении команды npx eslint . они должны отсутствовать. / 3.64
-
- есть команда npm run start, которая запускает сервер на localhost:3000;
- и npm run dev, которая запускает сервер на localhost:3000 с хот релоудом.
- Когда все зависимости установлены, приложение запускается командой npm run dev без ошибок. / 12.57
-
- запрос на GET /users/me возвращает информацию о пользователе (email и имя);
- PATCH /users/me — обновляет информацию о пользователе;
- GET /movies все сохранённые пользователем фильмы;
- POST /movies создаёт фильм с переданными в теле данными;
- DELETE /movies/movieId удаляет сохранённый фильм по _id;
- POST /signup создаёт пользователя с переданными в теле данными;
- POST /signin возвращает JWT, если в теле запроса переданы правильные почта и пароль.
- Если вы сохраняете JWT в куках, роут /signout должен удалять JWT из куки.
- Все роуты, кроме /signin и /signup, защищены авторизацией. / 3.64
- Роуты пользователей и роуты фильмов описаны в отдельных файлах. / 3.64
-
- если в запросе что-то не так, сервер возвращает ответ с ошибкой и её статусом;
- асинхронные обработчики завершены блоком catch;
- API не возвращает стандартных ошибок базы данных или Node.js.
- В production-режиме адрес базы данных берётся из process.env. / 3.64
-
- пароль хранится в виде хеша;
- API не возвращает хеш пароля клиенту.
- Данные валидируются перед добавлением в базу. / 3.64
- Пользователь не может удалить сохранённую карточку из профиля другого пользователя. / 3.64
- К серверу можно обратиться с помощью https по адресу домена, указанному в README.md. / 3.64
-
- для продакшн сборки он хранится в .env файле — этот файл не добавляется в git;
- в режиме разработки (при process.env.NODE_ENV !== 'production') код запускается и работает и без .env файла.
Хорошие практики
- Все роуты подключены в файле index.js, который находится в папке routes. Оттуда единый роут подключается в файле app.js / 1.5
- Асинхронные операции реализованы промисами или async/await. / 1.5
- Запрос валидируется перед передачей контроллеру. Тело и, где необходимо, заголовки и параметры, проверяются по соответствующим схемам. Если запрос не соответствует схеме, обработка не передаётся контроллеру, и клиент получает ошибку валидации. / 1.5
-
- запросы и ответы записываются в файл request.log;
- ошибки записываются в файл error.log;
- файлы логов не добавляются в репозиторий.
- Ошибки обрабатываются централизованным обработчиком. / 1.5
- Централизованный обработчик ошибок описан в отдельном модуле. / 1.5
- В случае ошибки API возвращает статус ответа, который соответствует типу ошибки. / 1.5
- К серверу можно обратиться по https по адресу домена, указанному в README.md. / 1.5
-
- Подходящий адрес: movies-explorer.nomoreparties.co/api.
- Неподходящий адрес: movies-explorer.nomoreparties.co.
Рекомендации
-
Для ошибок API созданы классы, расширяющие конструктор Error.
/ 0.8 - Используется модуль Helmet для установки заголовков, связанных с безопасностью. / 0.8
-
- адрес Mongo-сервера и секретный ключ для JWT в режиме разработки вынесены в отдельный конфигурационный файл;
- сообщения ответов и ошибок (константы приложения) вынесены в отдельный файл с константами.
- Настроен rate limiter: число запросов с одного IP в единицу времени ограничено. / 0.8
- rate limiter сконфигурирован в отдельном файле и импортируется в app.js. / 0.8
- API размещено на отдельном поддомене, например api.movies-explorer.nomoreparties.co. / 0.8
Вёрстка и JSX
Работа отклоняется от проверки
- Пул реквест не отправлен на проверку.
- Одна или более секций отсутствуют.
- Разметка не портирована в JSX.
Критерии, влияющие на работоспособность
- Проект адаптирован под различные разрешения экрана. Горизонтальный скролл не возникает на разрешениях от 320 пикселей и больше. Нельзя скрывать полосу прокрутки свойством overflow: hidden. / 14.29
- Проект соответствует сгенерированному под него макету.
- Все блоки из макета свёрстаны. Корректно работает навигация между страницами и ссылки на внешние ресурсы: ни одна ссылка не ведёт в пустоту или на якорь, внешние ссылки открываются в новой вкладке. На все страницы проекта можно попасть, а скрытые блоки можно отобразить. / 14.29
- Отзывчивая вёрстка, которая корректно тянется на всех промежуточных разрешениях. / 14.29
- Отсутствуют ошибки валидации при сборке приложения или в валидаторе. / 3.38
- В коде используется семантическая разметка: применяются семантические теги, выбор элементов при вёрстке корректен (параграф должен быть параграфом, список — списком); структура DOM-дерева состоит не только из контейнеров div. / 3.38
- Для позиционирования элементов выбран верный подход, описанный корректным синтаксисом. Например, при абсолютном позиционировании элемента его родительскому блоку задано относительное позиционирование. / 3.38
- Каркас макета реализован на Flex layout или Grid layout. / 3.38
- Работа модальных окон настроена. / 3.38
-
- разметка заключена в ( ), лишние пустые <div> для этого не используются, / 3.38
- разметка вынесена в соответствующие ей компоненты. / 3.38
-
- директория images/ с картинками, / 3.38
- директория components/ с JS и CSS-файлами компонентов, / 3.38
- директория fonts/ со шрифтами. / 3.38
Хорошие практики
- Именование классов сделано по БЭМ. / 2.14
- Кнопки, инпуты и ссылки реализованы во всех состояниях, указанных в макете. / 2.14
- В макете есть одинаковые элементы. Для их оформления должен быть переиспользован один компонент. / 2.14
- Шрифты подключены через @font-face. / 2.14
- Элементы формы должны выделяться, когда на них установлен фокус. Состояние фокуса, а также outline стилизованы в соответствии с макетом или на своё усмотрение. / 2.14
- У формы должны быть заданы плейсхолдеры и валидированы обязательные поля. / 2.14
- Reset.css запрещён. / 2.14
Рекомендации
- Для каждого шрифта указаны альтернативные варианты из системных шрифтов. / 1.67
- Для изображений задан атрибут alt с подходящим значением. / 1.67
- Растровые и векторные изображения оптимизированы. / 1.67
React и JS
Работа отклоняется от проверки
- Пул реквест не отправлен на проверку.
- Не работает описанная в задании функциональность. API поиска/сохранения/удаления фильмов, авторизации/регистрации/редактирования профиля не работают, либо при обращении к ним возникают ошибки в консоли.
- Фронтенд часть приложения не выложена на сервер;
Критерии, влияющие на работоспособность
-
- Прелоадер крутится в ожидании выполнения запроса.
- Все ссылки и кнопки в проекте работают.
- Все формы валидируются и на стороне клиента.
- На странице «Регистрация» клик по кнопке «Зарегистрироваться» при корректно введённых данных отправляет запрос на роут /signup. Если запрос прошёл успешно, то происходит редирект на страницу /movies.
- На странице «Авторизация» клик по кнопке «Войти» при корректно введённых данных отправляет запрос на роут /signin. Если запрос прошёл успешно, происходит редирект на страницу /movies.
- На странице редактирования профиля клик по кнопке «Сохранить» при корректно введённых данных отправляет запрос на роут /users/me. Если запрос прошёл успешно, пользователь получает соответствующее сообщение.
- При работе с полями ввода на страницах «Регистрация» и «Авторизация» кнопки сабмита формы заблокированы и ожидают введения валидных данных в инпуты.
- Правильно работают оба состояния шапки: если пользователь не залогинился, в шапке должны быть кнопки «Войти» и «Регистрация»; если пользователь залогинился, кнопки исчезают — появляются кнопки «Фильмы», «Сохранённые фильмы» и «Аккаунт».
- Работа с фильтром настроена. Если карточки уже были отображены на странице в блоке результатов, клик по чекбоксу «Короткометражки» приводит к повторной фильтрации результата. Повторный запрос к API либо выполняется повторно по истечению определённого времени (не при каждом поиске), либо не выполняется вовсе. Если запрос выполняется впервые, то работа с фильтром происходит после получения данных.
- После успешного сабмита формы поиска появляется блок с результатами. Если ничего не найдено, выводится надпись «Ничего не найдено».
- В блоке результата отображается один ряд из того количества карточек, которое было сгенерировано в макете. Нажатие на кнопку «Ещё» отображает следующий ряд карточек.
- Карточка состоит из изображения, названия фильма и его длительности. Длительность фильма рассчитывается корректно и соответствует формату, указанному в макете. Клик по карточке ведёт на трейлер фильма.
- Если пользователь закрыл вкладку, а после — вернулся на сайт, данные достаются из локального хранилища при монтировании компонента App.
- При клике на иконку «Лайк» в блоке карточки выполняется запрос к /movies нашего API.
- При клике на активную иконку «Лайк» в блоке карточки выполняется запрос на удаление карточки фильма. После успешного запроса карточка удаляется из раздела «Сохранённые фильмы».
- На странице «Сохранённые фильмы» отображается форма поиска. Она позволяет искать фильмы по уже полученным данным о сохранённых фильмах.
- На странице «Сохранённые фильмы» блок карточки содержит иконку удаления, а не лайка.
- При попытке перейти на несуществующую страницу происходит редирект на страницу «404». Кнопка «Назад» работает корректно.
- Удалённые/добавленные карточки фильмов появляются только после перезагрузки страницы. / 1.52
- Фильтрация по короткометражкам срабатывает после перезагрузки страницы. / 1.52
- Иконка «Лайк» не меняет свой статус после перезагрузки страницы. / 1.52
- При пустых полях ввода кнопка сабмита формы активна. / 1.52
- Когда отображены все фильмы по ключевому слову, кнопка «Ещё» скрывается только после перезагрузки страницы. / 1.52
- Если осталось отобразить меньше карточек фильмов, чем в полном ряду, то нажатие кнопки «Ещё» вызывает появления ошибок в консоли. / 1.52
- При удалении сохранённых карточек на соответствующей странице «Сохранённые фильмы» их по-прежнему можно найти через поиск. Поиск начинает корректно работать только после перезагрузки страницы. / 1.52
- Другие баги, которые возникают при работе с сервисом и требуют перезагрузки страницы или приложения. / 1.52
- Локальное хранилище: работа с jwt токеном и результатами поискового запроса выполнена в правильном порядке. / 1.52
- Сборка и запуск проекта выполняются без ошибок. / 1.52
- Создана глобальная стейт-переменная currentUser. / 1.52
- Jwt проверяется запросом к серверу, а не только в локальном хранилище. / 1.52
- Роуты /saved-movies, /movies, /profile защищены HOC-компонентом ProtectedRoute. / 2.16
- При попытке перейти на любой защищённый роут происходит редирект на /. / 2.16
- Если пользователь закрыл вкладку и был авторизован, он может вернуться сразу на любую страницу приложения по URL-адресу, кроме страниц авторизации и регистрации. / 2.16
- После успешной авторизации происходит редирект на /movies. Шапка сайта отвечает состоянию авторизованного пользователя и содержит все необходимые ссылки. / 2.16
- Если на странице редактирования профиля введённая информация соответствует текущим данным пользователя, кнопка «Сохранить» заблокирована. / 2.16
- Роуты /, /signin, /signup не являются защищёнными. / 2.16
- После успешного вызова обработчика onSignOut происходит редирект на /. / 2.16
- При выходе из аккаунта jwt удаляется. / 2.16
- Корректно используется хук useHistory. / 2.16
- Корректно используются компоненты <Switch />, <Route /> и <Redirect />. / 2.16
- Хуки не используются внутри условных блоков или циклов. / 2.16
- Хуки вызываются в основной функции компонента. / 2.16
- При использовании классовых компонентов эффекты описаны внутри методов жизненного цикла компонента. / 2.16
- Для элементов списка используется уникальный ключ key, а не индекс массива. / 2.16
- Компоненты Main, NavBar и SavedNewsHeader подписаны на контекст CurrentUserContext. / 2.16
- В компонент App внедрён контекст через CurrentUserContext.Provider. / 2.16
- В корневом компоненте App создана стейт-переменная currentUser. Она используется в качестве значения для провайдера контекста. / 2.16
- В корневом компоненте App описаны обработчики: onRegister, onLogin и onSignOut. Эти обработчики переданы в соответствующие компоненты: Register.js, Login.js и NavBar.js. / 2.16
- Запросы можно осуществлять через Fetch API или XMLHttpRequest.
- Сторонние библиотеки (такие как axios или jQuery) не применяются.
- Запросы к API вынесены в отдельные файлы: MainApi.js и MoviesApi.js Цепочка обработки промисов завершается блоком.
- Цепочка обработки промисов завершается блоком catch.
- Первый обработчик then возвращает res.json. res проверяется на корректность.
- camelCase для параметров, методов и переменных;
- существительные для имён переменных;
- существительные во множественном числе для NodeList;
- существительные с заглавной буквы для имён классов;
- const для неизменяемых напрямую переменных;
- имя класса соответствует содержимому;
- для именования запрещены: транслит и неуместные сокращения.
- Сторонние JavaScript-библиотеки не применяются. / 2.16
Хорошие практики
- Начальное состояние стейт-переменных содержит корректный тип данных. / 1.88
- Запрос к API за информацией о пользователе и массиве карточек выполняется единожды при монтировании. / 1.88
- Запросы к API описаны внутри компонента App или в корневых компонентах страниц. / 1.88
- В качестве функции-обработчика не передаются стрелочные функции. / 1.88
-
- пользователь получает сообщение в случае любой ошибки; / 1.88
- поля формы заблокированы во время отправки запросов. / 1.88
- Фиксированные значения (константы) именуются заглавными буквами и вынесены в отдельный конфиг-файл. / 1.88
Рекомендации
- Используются семантически правильные блоки для компонентов. / 1.67
- Не используются <div> или иные лишние HTML-теги для компонентов, которые состоят из одноуровневых блоков. / 1.67
-
- по имени колбэка слушателя понятно его назначение; / 0.3
- нет «магических значений» — все значения записаны в переменные; / 0.3
- константы описаны в той области видимости, в которой объявлена функция. Внутри функции значения констант берутся из замыкания. / 0.3