Бэкенд
Работа отклоняется от проверки
- 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 с хот релоудом.
-
- запрос на GET /users/me возвращает информацию о пользователе (email и имя);
- PATCH /users/me — обновляет информацию о пользователе;
- GET /movies все сохранённые пользователем фильмы;
- POST /movies создаёт фильм с переданными в теле данными;
- DELETE /movies/_id удаляет сохранённый фильм по _id;
- POST /signup создаёт пользователя с переданными в теле данными;
- POST /signin возвращает JWT, если в теле запроса переданы правильные почта и пароль.
- Если вы сохраняете JWT в куках, роут /signout должен удалять JWT из куки.
- Пользователь не может удалить сохранённую карточку из профиля другого пользователя. / 3.64
- Все роуты, кроме /signin и /signup, защищены авторизацией. / 3.64
- Роуты пользователей и роуты фильмов описаны в отдельных файлах. / 3.64
-
- используются статус-коды ошибок: 400, 401, 403, 404, 409, 500;
- если в запросе что-то не так, сервер возвращает статус ответа, который соответствует типу ошибки;
- сообщение об ошибке соответсвует ее типу;
- асинхронные обработчики завершены блоком catch;
- API не возвращает стандартных ошибок базы данных или Node.js.
-
- пароль хранится в виде хеша;
- API не возвращает хеш пароля клиенту.
-
- Запрос валидируется перед передачей контроллеру. Тело и, где необходимо, заголовки и параметры проверяются по соответствующим схемам. Если запрос не соответствует схеме, обработка не передаётся контроллеру, и клиент получает ошибку валидации.
- Данные валидируются перед добавлением в базу.
- В production-режиме адрес базы данных берётся из process.env. / 7.28
- К серверу можно обратиться с помощью https по адресу домена, указанному в README.md. / 3.64
-
- для продакшн сборки он хранится в .env файле — этот файл не добавляется в git;
- в режиме разработки (при process.env.NODE_ENV !== 'production') код запускается и работает и без .env файла.
Хорошие практики
- Все роуты подключены в файле index.js, который находится в папке routes. Оттуда единый роут подключается в файле app.js / 2.14
- Асинхронные операции реализованы промисами или async/await. / 2.14
- Валидация описана в отдельном модуле. / 2.14
-
- запросы и ответы записываются в файл request.log;
- ошибки записываются в файл error.log;
- файлы логов не добавляются в репозиторий.
- Ошибки обрабатываются централизованным обработчиком. / 2.14
- Централизованный обработчик ошибок описан в отдельном модуле. / 2.14
-
- Подходящий адрес:
movies-explorer.nomoreparties.co/api,
api.movies-explorer.nomoreparties.co. - Неподходящий адрес:
server-movies-explorer.nomoreparties.co,
movies-explorer.nomoreparties.co/sometext.
- Подходящий адрес:
Рекомендации
-
Для ошибок API созданы классы, расширяющие конструктор Error.
/ 0.71 - Используется модуль Helmet для установки заголовков, связанных с безопасностью. / 0.71
-
- адрес Mongo-сервера и секретный ключ для JWT в режиме разработки вынесены в отдельный конфигурационный файл;
- сообщения ответов и ошибок (константы приложения) вынесены в отдельный файл с константами.
- Настроен rate limiter: число запросов с одного IP в единицу времени ограничено. / 0.71
- rate limiter сконфигурирован в отдельном файле и импортируется в app.js. / 0.71
- Для имени базы данных используется bitfilmsdb / 0.71
Вёрстка и JSX
Работа отклоняется от проверки
- Пул реквест не отправлен на проверку.
- Одна или более секций отсутствуют.
- Разметка не портирована в JSX.
- Проект не соответствует сгенерированному под него макету.
Работа принимается, если соблюдены критерии работоспособности
- Проект адаптирован под различные разрешения экрана. Горизонтальный скролл не возникает на разрешениях от 320 пикселей и больше. Нельзя скрывать полосу прокрутки свойством overflow: hidden. / 11.55
- Все блоки из макета свёрстаны. Корректно работает навигация между страницами и ссылки на внешние ресурсы: ни одна ссылка не ведёт в пустоту или на якорь, внешние ссылки открываются в новой вкладке. На все страницы проекта можно попасть, а скрытые блоки можно отобразить. / 11.55
- Именование классов по БЭМ. / 11.55
- Отзывчивая вёрстка, которая корректно тянется на всех промежуточных разрешениях. / 11.55
- В коде используется семантическая разметка: применяются семантические теги, выбор элементов при вёрстке корректен (параграф должен быть параграфом, список — списком); структура DOM-дерева состоит не только из контейнеров div. / 3.38
- Для позиционирования элементов выбран верный подход, описанный корректным синтаксисом. Например, при абсолютном позиционировании элемента его родительскому блоку задано относительное позиционирование. / 3.38
- Каркас макета реализован на Flex layout или Grid layout. / 3.38
- Инфраструктурные файлы проекта созданы через CRA. / 3.38
- Работа модальных окон настроена верно. / 3.38
-
- разметка заключена в ( ), лишние пустые <div> для этого не используются, / 3.38
- разметка вынесена в соответствующие ей компоненты. / 3.38
-
- директория images/ с картинками, / 3.38
- директория components/ с JS и CSS-файлами компонентов, / 3.38
- директория fonts/ со шрифтами. / 3.38
Хорошие практики
- Кнопки, инпуты и ссылки реализованы во всех состояниях, указанных в макете. / 2.14
- В макете есть одинаковые элементы. Для их оформления должен быть переиспользован один компонент. / 2.14
- Шрифты подключены через @font-face. / 2.14
- Иконки экспортированы в формате SVG. / 2.14
- Элементы формы должны выделяться, когда на них установлен фокус. Состояние фокуса, а также outline стилизованы в соответствии с макетом или на своё усмотрение. / 2.14
- У формы должны быть заданы плейсхолдеры и валидированы обязательные поля. / 2.14
- Reset.css запрещён. / 2.14
Рекомендации
- Для каждого шрифта указаны альтернативные варианты из системных шрифтов. / 1.68
- Для изображений задан атрибут alt с подходящим значением. / 1.67
- Растровые и векторные изображения оптимизированы. / 1.67
React и JS
Работа отклоняется от проверки
- Пул реквест не отправлен на проверку.
- Не работает описанная в задании функциональность. API поиска/сохранения/удаления фильмов, авторизации/регистрации/редактирования профиля не работают, либо при обращении к ним возникают ошибки в консоли.
- Сборка или запуск проекта выполняются с ошибками.
- Фронтенд часть приложения не выложена на сервер;
Работа принимается, если соблюдены критерии работоспособности
-
-
Общее:
- Все ссылки и кнопки в проекте работают.
- Правильно работают оба состояния шапки: если пользователь не залогинился, в шапке должны быть кнопки «Войти» и «Регистрация»; если пользователь залогинился, кнопки исчезают — и появляются кнопки «Фильмы», «Сохранённые фильмы» и «Аккаунт», в том числе и на главной странице.
- При поиске текст запроса, найденные фильмы и состояние переключателя короткометражек сохраняются в хранилище. Если пользователь повторно переходит на страницу фильмов, то при монтировании компонента данные достаются из локального хранилища. Страница отображается в соответствии с загруженными из хранилища данными.
- Все формы валидируются и на стороне клиента. Пользователь не может отправить запрос с невалидными данными.
-
Страницы «Регистрация» и «Авторизация»:
- На странице «Регистрация» клик по кнопке «Зарегистрироваться» отправляет запрос на роут /signup, если данные введены корректно. Если запрос прошёл успешно, то автоматически производится вход и редирект на страницу /movies.
- На странице «Авторизация» клик по кнопке «Войти» отправляет запрос на роут /signin, если данные введены корректно. Если запрос прошёл успешно, происходит редирект на страницу /movies.
- Все формы валидируются и на стороне клиента.
-
Страница редактирование профиля:
- На странице редактирования профиля клик по кнопке «Сохранить» отправляет запрос на роут /users/me, если данные введены корректно.
- Пользователю отображается уведомление об успешном запросе к серверу при сохранении профиля.
- Если на странице редактирования профиля введённая информация соответствует текущим данным пользователя, кнопка «Сохранить» заблокирована и нельзя отправить запрос сохранения.
-
Поиск фильмов:
- Прелоадер крутится во время выполнения запроса фильмов.
- Работа с фильтром настроена:
- Поиск фильмов регистронезависимый.
- Если запрос выполняется впервые, то работа с фильтром происходит после получения данных.
- Если карточки уже были отображены на странице в блоке результатов, клик по чекбоксу «Короткометражки» приводит к повторной фильтрации результата.
- После успешного сабмита формы поиска появляется блок с результатами.
- Если ничего не найдено, выводится текст: «Ничего не найдено».
- На странице всех фильмов в блоке результата отображается такое же количество карточек, как в макете. Нажатие на кнопку «Ещё» отображает следующий ряд с тем же числом карточек. При отображении всех карточек кнопка "Ещё" скрывается.
-
Карточки:
- Карточка состоит из изображения, названия фильма и его длительности. Длительность фильма рассчитывается корректно и соответствует формату в макете. Клик по карточке ведёт на трейлер фильма.
- Кнопка лайка имеет правильное состояние, в зависимости от того, добавлен ли фильм в сохранённые или нет.
- При клике на иконку «Лайк» в блоке карточки выполняется запрос к /movies нашего API для установки или снятия лайка, в зависимости от текущего состояния.
-
На странице «Сохранённые фильмы»:
- отображается форма поиска. Она позволяет искать фильмы по уже полученным данным о сохранённых фильмах.
- Блок карточки содержит кнопку удаления, а не лайка.
- При нажатии на кнопку удаления выполняется запрос на удаление фильма. После успешного запроса карточка удаляется со страницы.
- Удалённые или добавленные карточки фильмов появляются только после перезагрузки страницы.
- Если осталось отобразить меньше карточек фильмов, чем в полном ряду, то нажатие кнопки «Ещё» вызывает появление ошибок в консоли.
- При удалении сохранённых карточек на соответствующей странице «Сохранённые фильмы» их по-прежнему можно найти через поиск. Поиск начинает корректно работать только после перезагрузки страницы.
- Другие баги, которые возникают при работе с сервисом и требуют перезагрузки страницы или «ломают» пользовательский опыт.
- Роуты /saved-movies, /movies, /profile защищёны HOC-компонентом ProtectedRoute. Роуты / , /signin, /signup не защищены. / 2
- При попытке перейти на любой защищённый роут происходит редирект на /. / 3
- Если пользователь был авторизован и закрыл вкладку, он может вернуться сразу на любую страницу приложения по URL-адресу, кроме страниц авторизации и регистрации. / 2
- После успешного вызова обработчика onSignOut происходит редирект на /. / 2
- Корректно используется хук useHistory. / 1
- При попытке перейти на несуществующую страницу происходит редирект на страницу «404». Кнопка «Назад» работает корректно. / 2
- Корректно используются компоненты <Switch />, <Route /> и <Redirect />. / 1
- JWT-токен хранится в localStorage или в cookie; / 2
- Jwt проверяется запросом к серверу, а не только в локальном хранилище. / 2
- При выходе из аккаунта jwt удаляется. / 3
- Хуки не используются внутри условных блоков или циклов. / 1
- Хуки вызываются в основной функции компонента. / 1
- При использовании классовых компонентов эффекты описаны внутри методов жизненного цикла компонента. / 1
- Имена пользовательских хуков начинаются с use. / 2
- В корневом компоненте App создана стейт-переменная, которая хранит данные пользователя. Она используется в качестве значения для провайдера контекста. / 1
- В компонент App внедрён контекст через CurrentUserContext.Provider. / 1
- Компоненты, в которых используются данные профиля, подписаны на контекст. / 1
- Запросы можно осуществлять через Fetch API или XMLHttpRequest, сторонние библиотеки, такие как axios или jQuery), не применяются. / 1
- Запросы к API вынесены в отдельные файлы: MainApi.js и MoviesApi.js. Цепочка обработки промисов завершается блоком. / 1
- Первый обработчик then возвращает res.json. res проверяется на корректность. / 1
- Цепочка обработки промисов завершается блоком catch. / 1
- Не выполняются лишние запросы к бэкенду, например: запрос всех фильмов с сервиса beatfilm-movies производится только при первом поиске; все сохранённые фильмы не запрашиваются с сервера при каждом лайке или дизлайке; данные пользователя запрашиваются один раз при запуске приложения. / 2
- имена переменных, функций и параметров написаны в camelCase;
- имена переменных — существительные;
- имена переменных, функций и компонентов соответствуют содержимому;
- имена коллекций NodeList — существительные во множественном числе;
- имя функции начинается с глагола и отражает то, что она делает;
- для именования запрещены: транслит и неуместные сокращения.
Хорошие практики
- Начальное состояние стейт-переменных содержит корректный тип данных. / 1
- Для элементов списка используется уникальный ключ key, а не индекс массива. / 2
- Запросы к API описаны внутри компонента App или в корневых компонентах страниц. / 2
- Для внутренних ссылок в приложении используются компоненты из библиотеки react-router. / 2
- Не происходит утечки памяти при навешивании обработчиков. Все обработчики, добавленные через addEventListener, удаляются при размонтировании компонента. / 2
-
- пользователь получает сообщение в случае любой ошибки; / 4
- поля формы заблокированы во время отправки запросов, и у пользователя нет возможности отправить новый запрос до завершения предыдущего. / 2
- Фиксированные значения (константы) именуются заглавными буквами и вынесены в отдельный конфиг-файл. / 2
Рекомендации
- Сторонние JavaScript-библиотеки не применяются. / 2
- Используются семантически правильные блоки для компонентов. Не используются <div> или иные обертки для компонентов, которые состоят из одноуровневых блоков. / 1
-
- нет беспорядка в коде;
- нет лишнего кода: например, переменная объявлена, но не используется, или есть какая-то избыточная логика;
- код форматирован одинаково, соблюдается иерархия отступов.
-
Общее: