From bf06c357b9c28a3847bf9c49441f4002a04b9660 Mon Sep 17 00:00:00 2001 From: Vlad Possin Date: Thu, 24 Dec 2020 21:05:58 +0600 Subject: [PATCH] created homework_7 --- projects/cookie/cookie.html | 55 ++++++++ projects/cookie/cookie.spec.js | 250 +++++++++++++++++++++++++++++++++ projects/cookie/index.js | 135 ++++++++++++++++++ 3 files changed, 440 insertions(+) create mode 100644 projects/cookie/cookie.html create mode 100644 projects/cookie/cookie.spec.js create mode 100644 projects/cookie/index.js diff --git a/projects/cookie/cookie.html b/projects/cookie/cookie.html new file mode 100644 index 0000000..766c545 --- /dev/null +++ b/projects/cookie/cookie.html @@ -0,0 +1,55 @@ + + +
+
+ Поиск cookie: +
+
+
+ Добавить cookie:
+
+
+ +
+
+
+ Доступные cookie: + + + + + + + + + + + +
имязначениеудалить
+
+
diff --git a/projects/cookie/cookie.spec.js b/projects/cookie/cookie.spec.js new file mode 100644 index 0000000..d09d615 --- /dev/null +++ b/projects/cookie/cookie.spec.js @@ -0,0 +1,250 @@ +const hasOwnProperty = Object.prototype.hasOwnProperty; + +function getCookies() { + return document.cookie + .split('; ') + .filter(Boolean) + .map((cookie) => cookie.match(/^([^=]+)=(.+)/)) + .reduce((obj, [, name, value]) => { + obj[name] = value; + + return obj; + }, {}); +} + +describe('ДЗ 7.2 - Cookie editor', () => { + require('./index'); + + const app = document.querySelector('#app'); + let filterNameInput; + let addNameInput; + let addValueInput; + let addButton; + let listTable; + + describe('Интеграционное тестирование', () => { + beforeEach(() => { + const oldCookies = getCookies(); + + Object.keys(oldCookies).forEach( + (cookie) => (document.cookie = `${cookie}=;expires=${new Date(0)}`) + ); + + if (listTable) { + listTable.innerHTML = ''; + } + }); + + it('на старнице должны быть элементы с нужными id', () => { + filterNameInput = app.querySelector('#filter-name-input'); + addNameInput = app.querySelector('#add-name-input'); + addValueInput = app.querySelector('#add-value-input'); + addButton = app.querySelector('#add-button'); + listTable = app.querySelector('#list-table tbody'); + + expect(filterNameInput).toBeInstanceOf(Element); + expect(addNameInput).toBeInstanceOf(Element); + expect(addValueInput).toBeInstanceOf(Element); + expect(addButton).toBeInstanceOf(Element); + expect(listTable).toBeInstanceOf(Element); + }); + + it('cookie должны добавляться при нажатии на "добавить"', () => { + let cookies; + + addNameInput.value = 'test-cookie-name-1'; + addValueInput.value = 'test-cookie-value-1'; + addButton.click(); + + cookies = getCookies(); + expect(hasOwnProperty.call(cookies, addNameInput.value)); + expect(cookies[addNameInput.value]).toBe(addValueInput.value); + expect(listTable.children.length).toBe(1); + + addNameInput.value = 'test-cookie-name-2'; + addValueInput.value = 'test-cookie-value-2'; + addButton.click(); + + cookies = getCookies(); + expect(hasOwnProperty.call(cookies, addNameInput.value)); + expect(cookies[addNameInput.value]).toBe(addValueInput.value); + expect(listTable.children.length).toBe(2); + }); + + it('если при добавлении указано имя существующей cookie, то в таблице не должно быть дублей', () => { + addNameInput.value = 'test-cookie-name-1'; + addValueInput.value = 'test-cookie-value-1'; + addButton.click(); + + addNameInput.value = 'test-cookie-name-2'; + addValueInput.value = 'test-cookie-value-2'; + addButton.click(); + + addNameInput.value = 'test-cookie-name-2'; + addValueInput.value = 'test-cookie-value-2'; + addButton.click(); + + const cookies = getCookies(); + expect(hasOwnProperty.call(cookies, addNameInput.value)); + expect(cookies[addNameInput.value]).toBe(addValueInput.value); + expect(listTable.children.length).toBe(2); + }); + + it('если при добавлении указано имя существующей cookie, то в таблице должно быть изменено ее значение', () => { + addNameInput.value = 'test-cookie-name-1'; + addValueInput.value = 'test-cookie-value-1'; + addButton.click(); + + addNameInput.value = 'test-cookie-name-2'; + addValueInput.value = 'test-cookie-value-2'; + addButton.click(); + + addNameInput.value = 'test-cookie-name-2'; + addValueInput.value = 'other-test-cookie-value-2'; + addButton.click(); + + const rows = [...listTable.children]; + const changedRow = rows.filter( + (row) => row.children[1].textContent.trim() === 'other-test-cookie-value-2' + ); + expect(changedRow.length).toBe(1); + }); + + it('cookie должны удаляться при нажатии на "удалить"', () => { + let cookies; + let deleteButton; + + addNameInput.value = 'test-cookie-name-1'; + addValueInput.value = 'test-cookie-value-1'; + addButton.click(); + + addNameInput.value = 'test-cookie-name-2'; + addValueInput.value = 'test-cookie-value-2'; + addButton.click(); + + deleteButton = listTable.querySelector('button'); + + deleteButton.click(); + cookies = getCookies(); + expect(Object.keys(cookies).length).toBe(1); + expect(listTable.children.length).toBe(1); + + deleteButton = listTable.querySelector('button'); + deleteButton.click(); + cookies = getCookies(); + expect(Object.keys(cookies).length).toBe(0); + expect(listTable.children.length).toBe(0); + }); + + describe('Фильтрация', () => { + it('выводить список cookie, имя или значение которых соответствует фильтру', () => { + addNameInput.value = 'test-cookie-name-1'; + addValueInput.value = 'test-cookie-value-1'; + addButton.click(); + + addNameInput.value = 'test-cookie-name-2'; + addValueInput.value = 'test-cookie-value-2'; + addButton.click(); + + filterNameInput.value = 'test-cookie'; + filterNameInput.dispatchEvent(new KeyboardEvent('input')); + expect(listTable.children.length).toBe(2); + + filterNameInput.value = 'name-1'; + filterNameInput.dispatchEvent(new KeyboardEvent('input')); + expect(listTable.children.length).toBe(1); + + filterNameInput.value = 'name-2'; + filterNameInput.dispatchEvent(new KeyboardEvent('input')); + expect(listTable.children.length).toBe(1); + }); + + it('добавлять cookie в таблицу, только если значение cookie соответствует фильтру', () => { + addNameInput.value = 'test-cookie-name-1'; + addValueInput.value = 'test-cookie-value-1'; + addButton.click(); + + addNameInput.value = 'test-cookie-name-2'; + addValueInput.value = 'test-cookie-value-2'; + addButton.click(); + + filterNameInput.value = 'value-2'; + filterNameInput.dispatchEvent(new KeyboardEvent('input')); + expect(listTable.children.length).toBe(1); + + addNameInput.value = 'test-cookie-name-3'; + addValueInput.value = 'test-cookie-more-value-2'; + addButton.click(); + + const cookies = getCookies(); + expect(hasOwnProperty.call(cookies, addNameInput.value)); + expect(cookies[addNameInput.value]).toBe(addValueInput.value); + expect(listTable.children.length).toBe(2); + }); + + it('не добавлять cookie в таблицу, если значение cookie не соответствует фильтру', () => { + addNameInput.value = 'test-cookie-name-1'; + addValueInput.value = 'test-cookie-value-1'; + addButton.click(); + + addNameInput.value = 'test-cookie-name-2'; + addValueInput.value = 'test-cookie-value-2'; + addButton.click(); + + filterNameInput.value = 'value-2'; + filterNameInput.dispatchEvent(new KeyboardEvent('input')); + expect(listTable.children.length).toBe(2); + + addNameInput.value = 'test-cookie-name-3'; + addValueInput.value = 'test-cookie-value-3'; + addButton.click(); + + const cookies = getCookies(); + expect(hasOwnProperty.call(cookies, addNameInput.value)); + expect(cookies[addNameInput.value]).toBe(addValueInput.value); + expect(listTable.children.length).toBe(1); + }); + + it('удалить cookie из табилицы, если ее значение перестало соответствовать фильтр', () => { + addNameInput.value = 'test-cookie-name-1'; + addValueInput.value = 'test-cookie-value-1'; + addButton.click(); + + addNameInput.value = 'test-cookie-name-2'; + addValueInput.value = 'test-cookie-value-2'; + addButton.click(); + + addNameInput.value = 'test-cookie-name-3'; + addValueInput.value = 'test-cookie-value-2'; + addButton.click(); + + filterNameInput.value = 'value-2'; + filterNameInput.dispatchEvent(new KeyboardEvent('input')); + expect(listTable.children.length).toBe(2); + + addNameInput.value = 'test-cookie-name-3'; + addValueInput.value = 'test-cookie-value-3'; + addButton.click(); + + const cookies = getCookies(); + expect(hasOwnProperty.call(cookies, addNameInput.value)); + expect(cookies[addNameInput.value]).toBe(addValueInput.value); + expect(listTable.children.length).toBe(1); + }); + + it('выводить все cookie, если фильтр не задан', () => { + addNameInput.value = 'test-cookie-name-1'; + addValueInput.value = 'test-cookie-value-1'; + addButton.click(); + + addNameInput.value = 'test-cookie-name-2'; + addValueInput.value = 'test-cookie-value-2'; + addButton.click(); + + filterNameInput.value = ''; + filterNameInput.dispatchEvent(new KeyboardEvent('input')); + expect(listTable.children.length).toBe(3); + }); + }); + }); +}); diff --git a/projects/cookie/index.js b/projects/cookie/index.js new file mode 100644 index 0000000..05c1ecb --- /dev/null +++ b/projects/cookie/index.js @@ -0,0 +1,135 @@ +/* + ДЗ 7 - Создать редактор cookie с возможностью фильтрации + + 7.1: На странице должна быть таблица со списком имеющихся cookie. Таблица должна иметь следующие столбцы: + - имя + - значение + - удалить (при нажатии на кнопку, выбранная cookie удаляется из браузера и таблицы) + + 7.2: На странице должна быть форма для добавления новой cookie. Форма должна содержать следующие поля: + - имя + - значение + - добавить (при нажатии на кнопку, в браузер и таблицу добавляется новая cookie с указанным именем и значением) + + Если добавляется cookie с именем уже существующей cookie, то ее значение в браузере и таблице должно быть обновлено + + 7.3: На странице должно быть текстовое поле для фильтрации cookie + В таблице должны быть только те cookie, в имени или значении которых, хотя бы частично, есть введенное значение + Если в поле фильтра пусто, то должны выводиться все доступные cookie + Если добавляемая cookie не соответствует фильтру, то она должна быть добавлена только в браузер, но не в таблицу + Если добавляется cookie, с именем уже существующей cookie и ее новое значение не соответствует фильтру, + то ее значение должно быть обновлено в браузере, а из таблицы cookie должна быть удалена + + Запрещено использовать сторонние библиотеки. Разрешено пользоваться только тем, что встроено в браузер + */ + +import './cookie.html'; + +/* + app - это контейнер для всех ваших домашних заданий + Если вы создаете новые html-элементы и добавляете их на страницу, то добавляйте их только в этот контейнер + + Пример: + const newDiv = document.createElement('div'); + homeworkContainer.appendChild(newDiv); + */ +const homeworkContainer = document.querySelector('#homework-container'); +// текстовое поле для фильтрации cookie +const filterNameInput = homeworkContainer.querySelector('#filter-name-input'); +// текстовое поле с именем cookie +const addNameInput = homeworkContainer.querySelector('#add-name-input'); +// текстовое поле со значением cookie +const addValueInput = homeworkContainer.querySelector('#add-value-input'); +// кнопка "добавить cookie" +const addButton = homeworkContainer.querySelector('#add-button'); +// таблица со списком cookie +const listTable = homeworkContainer.querySelector('#list-table tbody'); + +const cookiesMap = getCookies(); +let filterValue = ''; + +updateTable(); + +function getCookies() { + return document.cookie + .split('; ') + .filter(Boolean) + .map((cookie) => cookie.match(/^([^=]+)=(.+)/)) + .reduce((obj, [, name, value]) => { + obj.set(name, value); + + return obj; + }, new Map()); +} + +filterNameInput.addEventListener('input', function () { + filterValue = this.value; + updateTable(); +}); + +addButton.addEventListener('click', () => { + const name = encodeURIComponent(addNameInput.value.trim()); + const value = encodeURIComponent(addValueInput.value.trim()); + + if (!name) { + return; + } + + document.cookie = `${name}=${value}`; + cookiesMap.set(name, value); + + updateTable(); +}); + +listTable.addEventListener('click', (e) => { + const { role, cookieName } = e.target.dataset; + + if (role === 'remove-cookie') { + cookiesMap.delete(cookieName); + document.cookie = `${cookieName}=deleted; max-age=0`; + updateTable(); + } +}); + +function updateTable() { + const fragment = document.createDocumentFragment(); + let total = 0; + + listTable.innerHTML = ''; + + for (const [name, value] of cookiesMap) { + if ( + filterValue && + !name.toLowerCase().includes(filterValue.toLowerCase()) && + !value.toLowerCase().includes(filterValue.toLowerCase()) + ) { + continue; + } + + total++; + + const tr = document.createElement('tr'); + const nameTD = document.createElement('td'); + const valueTD = document.createElement('td'); + const removeTD = document.createElement('td'); + const removeButton = document.createElement('button'); + + removeButton.dataset.role = 'remove-cookie'; + removeButton.dataset.cookieName = name; + removeButton.textContent = 'Удалить'; + nameTD.textContent = name; + valueTD.textContent = value; + valueTD.classList.add('value'); + tr.append(nameTD, valueTD, removeTD); + removeTD.append(removeButton); + + fragment.append(tr); + } + + if (total) { + listTable.parentNode.classList.remove('hidden'); + listTable.append(fragment); + } else { + listTable.parentNode.classList.add('hidden'); + } +}