From 789e718492fae34f8d9104375cf3422e5e96aee7 Mon Sep 17 00:00:00 2001 From: sseezov Date: Wed, 27 Mar 2024 18:11:37 +0700 Subject: [PATCH] little mess --- README.md | 40 ++++++++++++++++ __tests__/__fixtures__/index.html | 13 +----- __tests__/index.test.js | 25 ++++------ index.html | 4 ++ src/application.js | 78 +++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 4fe873a..faf172a 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,19 @@ ## Запуск и сборка приложения Для запуска фронтенда приложения используйте команду: +<<<<<<< HEAD +======= + +>>>>>>> 02f9cff (delete branch) ```bash make run ``` Для запуска сервера используйте в отдельном терминале команду: +<<<<<<< HEAD +======= + +>>>>>>> 02f9cff (delete branch) ```bash make start-server ``` @@ -20,16 +28,36 @@ make start-server ## Задача 1 +<<<<<<< HEAD Напишите и экспортируйте функцию `validateName()`, которая валидирует строку с условием, что валидным именем считается любая строка с длиной больше 0, исключая пробелы. Если имя валидно, то функция возвращает пустой объект, иначе возвращается объект с ключом errors, который содержит массив со строкой 'введите имя'. ```javascript validateName('example'); // [] validateName(''); // ['name cannot be empty'] validateName(' '); // ['name cannot be empty'] +======= +Напишите и экспортируйте по умолчанию функцию `app()`, отвечающую за работу веб-приложения. +При старте приложения должна рендериться форма внутри родительского элемента с классом `.form-container`. +Форма выглядит следующим образом. Для скорости работы, вы можете добавить ее через `innerHTML`. + +```html +
+
+ + +
+
+ + +
+ +
+>>>>>>> 02f9cff (delete branch) ``` ## Задача 2 +<<<<<<< HEAD Напишите и экспортируйте функцию `validateEmail()`, которая валидирует email, с условием, что валидной почтой считается любая строка с символом `@` посередине, с любой длиной символов, исключая пробелы до и после нее. Если почта валидна, то функция возвращает пустой объект, иначе возвращается объект с ключом errors, который содержит массив со строкой 'введите валидный email'. ```javascript @@ -52,6 +80,18 @@ validateEmail('g@s'); // [] ## Задача 5 При нажатии кнопки `зарегистрироваться` должен отправляться запрос на сервер с данными формы и в случае успешного ответа содержимое `document.body` нужно заменить на текст ответа сервера, завернутый в теги `

` таким образом: +======= +Форма, данная в файле **index.html**, имеет кнопку `submit` c текстом `'зарегистрироваться'`. Ваша задача состоит в том, чтобы реализовать для этой кнопки статус `disabled`, когда хотя бы одно из полей невалидно. Иначе кнопка не должна иметь атрибут `disabled`. + +## Задача 3 + +Внутри функции `app()` напишите код, который реализует контролируемый input для каждого поля формы. Инпут должны иметь класс `is-valid`, если его содержимое валидно. Иначе input должен иметь класс `is-invalid`. + +## Задача 4 + +При нажатии кнопки `зарегистрироваться` должен отправляться запрос на сервер с данными формы и в случае успешного ответа содержимое `document.body` нужно заменить на текст ответа сервера, завернутый в теги `

` таким образом: + +>>>>>>> 02f9cff (delete branch) ```html `

Ответ сервера

`. ``` diff --git a/__tests__/__fixtures__/index.html b/__tests__/__fixtures__/index.html index b0c5db0..b07aae1 100644 --- a/__tests__/__fixtures__/index.html +++ b/__tests__/__fixtures__/index.html @@ -2,18 +2,7 @@

Регистрация

-
-
- - -
-
- - -
- -
+
diff --git a/__tests__/index.test.js b/__tests__/index.test.js index cc58faa..abbf476 100644 --- a/__tests__/index.test.js +++ b/__tests__/index.test.js @@ -2,10 +2,10 @@ import '@testing-library/jest-dom'; import fs from 'fs'; import path from 'path'; -import testingLibrary, { configure } from '@testing-library/dom'; +import testingLibrary from '@testing-library/dom'; import userEvent from '@testing-library/user-event'; import nock from 'nock'; -import * as app from '../src/application.js'; +import run from '../src/application.js'; const { screen, waitFor } = testingLibrary; nock.disableNetConnect(); @@ -16,7 +16,6 @@ beforeEach(() => { const pathToFixture = path.join('__tests__', '__fixtures__', 'index.html'); const initHtml = fs.readFileSync(pathToFixture).toString(); document.body.innerHTML = initHtml; - const run = app.run ? app.run : () => { } run(); elements = { @@ -27,20 +26,13 @@ beforeEach(() => { }); test('step1', async () => { - expect(app.validateName('example@gmail.com')).toEqual([]); - expect(app.validateName('')).toEqual(['name cannot be empty']); - expect(app.validateName(' ')).toEqual(['name cannot be empty']); - expect(app.validateName('e')).toEqual([]); + const formContainer = document.querySelector('.form-container'); + expect(formContainer.querySelector('form') + .querySelector('.form-group') + .querySelector('input[class="form-control"]')).not.toEqual(null); }); test('step2', async () => { - expect(app.validateEmail('example@gmail.com')).toEqual([]); - expect(app.validateEmail(' @mail.com')).toEqual(['invalid email']); - expect(app.validateEmail('hhhhh @ g m a i l . c o m')).toEqual(['invalid email']); - expect(app.validateEmail('s@s')).toEqual([]); -}); - -test('step3', async () => { await userEvent.type(elements.nameInput, 'Petya'); await userEvent.type(elements.emailInput, 'wrong-email'); expect(elements.submit).toBeDisabled(); @@ -58,7 +50,7 @@ test('step3', async () => { expect(elements.submit).not.toBeDisabled(); }); -test('step4', async () => { +test('step3', async () => { await userEvent.clear(elements.nameInput); await userEvent.clear(elements.emailInput); await userEvent.type(elements.nameInput, 'Petya'); @@ -81,7 +73,7 @@ test('step4', async () => { }); -test('step5', async () => { +test('step4', async () => { let scope = nock('http://localhost') .post('/users') .reply(200, { @@ -104,7 +96,6 @@ test('step5', async () => { const pathToFixture = path.join('__tests__', '__fixtures__', 'index.html'); const initHtml = fs.readFileSync(pathToFixture).toString(); document.body.innerHTML = initHtml; - const run = app.run ? app.run : () => { } run(); elements = { diff --git a/index.html b/index.html index 2714533..8c3c0fc 100644 --- a/index.html +++ b/index.html @@ -13,6 +13,7 @@

Регистрация

+<<<<<<< HEAD
@@ -24,6 +25,9 @@

Регистрация

+======= +
+>>>>>>> 02f9cff (delete branch)
diff --git a/src/application.js b/src/application.js index e69de29..c033a1b 100644 --- a/src/application.js +++ b/src/application.js @@ -0,0 +1,78 @@ +import _ from 'lodash'; +import onChange from 'on-change'; +import axios from 'axios'; + +export const validateName = (name) => (name.trim().length ? [] : ['name cannot be empty']); +export const validateEmail = (email) => (/\w+@\w+/.test(email) ? [] : ['invalid email']); +const validateField = (fieldname, data) => (fieldname === 'name' ? validateName(data) : validateEmail(data)); + +export default () => { + const formHTML = ` +
+
+ + +
+
+ + +
+ +
`; + + const formContainer = document.querySelector('.form-container'); + formContainer.innerHTML = formHTML; + + const state = { + errors: { + name: [], + email: [], + }, + values: { + name: '', + email: '', + }, + }; + + const form = document.querySelector('form'); + const submit = document.querySelector('[type="submit"]'); + + const hasErrors = () => (_.values(state.errors).reduce((acc, curr) => (curr.length > 0 + ? acc.concat(curr) + : acc), []) + .length > 0); + + const watchedState = onChange(state, (path) => { + const selector = path.split('.')[1]; + const input = document.querySelector(`[name=${selector}]`); + const isFieldValid = validateField(selector, state.values[selector]).length === 0; + if (!isFieldValid) { + input.classList.remove('is-valid'); + input.classList.add('is-invalid'); + } else { + input.classList.remove('is-invalid'); + input.classList.add('is-valid'); + } + submit.disabled = hasErrors(state); + }); + + form.addEventListener('input', (e) => { + e.preventDefault(); + const targetName = e.target.name; + const targetData = new FormData(form).get(targetName); + watchedState.values[targetName] = targetData; + watchedState.errors[targetName] = (validateField(targetName, targetData)); + }); + + form.addEventListener('submit', (e) => { + e.preventDefault(); + axios.post('/users', state.values) + .then((response) => { + document.body.innerHTML = `

${response.data.message}

`; + }) + .catch((error) => { + console.log(error); + }); + }); +};