Критерии диплома веб-разработчика

Мы составили критерии проверки дипломного проекта. За выполнение каждого критерия начисляются баллы. Чтобы сдать дипломную работу, нужно набрать не меньше 80-ти баллов.

Критерии имеют разный вес. Они разделены на блоки:

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

Бэкенд

Нумерация

Работа отклоняется от проверки

  • 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