Skip to content

Commit

Permalink
little mess
Browse files Browse the repository at this point in the history
  • Loading branch information
sseezov committed Mar 27, 2024
1 parent 5c25fe6 commit 789e718
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 29 deletions.
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@
## Запуск и сборка приложения

Для запуска фронтенда приложения используйте команду:
<<<<<<< HEAD
=======

>>>>>>> 02f9cff (delete branch)
```bash
make run
```

Для запуска сервера используйте в отдельном терминале команду:
<<<<<<< HEAD
=======

>>>>>>> 02f9cff (delete branch)
```bash
make start-server
```
Expand All @@ -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
<form id="registrationForm">
<div class="form-group">
<label for="inputName">Name</label>
<input type="text" class="form-control" id="inputName" placeholder="Введите ваше имя" name="name" required>
</div>
<div class="form-group">
<label for="inputEmail">Email</label>
<input type="text" class="form-control" id="inputEmail" placeholder="Введите email" name="email" required>
</div>
<input type="submit" value="Submit" class="btn btn-primary" disabled>
</form>
>>>>>>> 02f9cff (delete branch)
```

## Задача 2

<<<<<<< HEAD
Напишите и экспортируйте функцию `validateEmail()`, которая валидирует email, с условием, что валидной почтой считается любая строка с символом `@` посередине, с любой длиной символов, исключая пробелы до и после нее. Если почта валидна, то функция возвращает пустой объект, иначе возвращается объект с ключом errors, который содержит массив со строкой 'введите валидный email'.

```javascript
Expand All @@ -52,6 +80,18 @@ validateEmail('g@s'); // []
## Задача 5

При нажатии кнопки `зарегистрироваться` должен отправляться запрос на сервер с данными формы и в случае успешного ответа содержимое `document.body` нужно заменить на текст ответа сервера, завернутый в теги `<p></p>` таким образом:
=======
Форма, данная в файле **index.html**, имеет кнопку `submit` c текстом `'зарегистрироваться'`. Ваша задача состоит в том, чтобы реализовать для этой кнопки статус `disabled`, когда хотя бы одно из полей невалидно. Иначе кнопка не должна иметь атрибут `disabled`.

## Задача 3

Внутри функции `app()` напишите код, который реализует контролируемый input для каждого поля формы. Инпут должны иметь класс `is-valid`, если его содержимое валидно. Иначе input должен иметь класс `is-invalid`.

## Задача 4

При нажатии кнопки `зарегистрироваться` должен отправляться запрос на сервер с данными формы и в случае успешного ответа содержимое `document.body` нужно заменить на текст ответа сервера, завернутый в теги `<p></p>` таким образом:

>>>>>>> 02f9cff (delete branch)
```html
`<p>Ответ сервера</p>`.
```
13 changes: 1 addition & 12 deletions __tests__/__fixtures__/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,7 @@
<div class="row justify-content-center">
<div class="col-md-6">
<h2 class="mb-4">Регистрация</h2>
<form id="registrationForm">
<div class="form-group">
<label for="inputName">Name</label>
<input type="text" class="form-control" id="inputName" placeholder="Введите ваше имя" name="name" required>
</div>
<div class="form-group">
<label for="inputEmail">Email</label>
<input type="text" class="form-control" id="inputEmail" placeholder="Введите email"
name="email" required>
</div>
<input type="submit" value="Submit" class="btn btn-primary" disabled>
</form>
<div class="form-container"></div>
</div>
</div>
</div>
25 changes: 8 additions & 17 deletions __tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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 = {
Expand All @@ -27,20 +26,13 @@ beforeEach(() => {
});

test('step1', async () => {
expect(app.validateName('[email protected]')).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('[email protected]')).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();
Expand All @@ -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');
Expand All @@ -81,7 +73,7 @@ test('step4', async () => {
});


test('step5', async () => {
test('step4', async () => {
let scope = nock('http://localhost')
.post('/users')
.reply(200, {
Expand All @@ -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 = {
Expand Down
4 changes: 4 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<div class="row justify-content-center">
<div class="col-md-6">
<h2 class="mb-4">Регистрация</h2>
<<<<<<< HEAD
<form id="registrationForm">
<div class="form-group">
<label for="inputName">Name</label>
Expand All @@ -24,6 +25,9 @@ <h2 class="mb-4">Регистрация</h2>
</div>
<input type="submit" value="Submit" class="btn btn-primary" disabled>
</form>
=======
<div class="form-container"></div>
>>>>>>> 02f9cff (delete branch)
</div>
</div>
</div>
Expand Down
78 changes: 78 additions & 0 deletions src/application.js
Original file line number Diff line number Diff line change
@@ -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 = `
<form id="registrationForm">
<div class="form-group">
<label for="inputName">Name</label>
<input type="text" class="form-control" id="inputName" placeholder="Введите ваше имя" name="name" required>
</div>
<div class="form-group">
<label for="inputEmail">Email</label>
<input type="text" class="form-control" id="inputEmail" placeholder="Введите email"
name="email" required>
</div>
<input type="submit" value="Submit" class="btn btn-primary" disabled>
</form>`;

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 = `<p>${response.data.message}</p>`;
})
.catch((error) => {
console.log(error);
});
});
};

0 comments on commit 789e718

Please sign in to comment.