From 517ee53c9f0a1c1ace15fcf6a65e28e756eb0869 Mon Sep 17 00:00:00 2001 From: naumenko-tanya Date: Fri, 26 Jul 2024 09:30:16 +0300 Subject: [PATCH 01/15] Delete non-admin user deletion button in workspace --- .../templates/workspace/wks-users.html | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/main/resources/templates/workspace/wks-users.html b/src/main/resources/templates/workspace/wks-users.html index b7023c12..642f6b0b 100644 --- a/src/main/resources/templates/workspace/wks-users.html +++ b/src/main/resources/templates/workspace/wks-users.html @@ -103,7 +103,7 @@ - + @@ -121,24 +121,8 @@ - - -
-
-
- -
-
- -
-
-
-
-
- - + +
From 154196d84abaa9e3927d3832dc22fdacb3bf0838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D0=B8=D0=BD=D0=B0=20=D0=91=D0=B5=D0=BB?= =?UTF-8?q?=D1=8F=D0=BA=D0=B0=D0=B5=D0=B2=D0=B0?= Date: Thu, 1 Aug 2024 17:36:33 +0300 Subject: [PATCH 02/15] rework the script connection #283 --- .../templates/workspace/wks-integration.html | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/resources/templates/workspace/wks-integration.html b/src/main/resources/templates/workspace/wks-integration.html index f0d431b2..22e7817a 100644 --- a/src/main/resources/templates/workspace/wks-integration.html +++ b/src/main/resources/templates/workspace/wks-integration.html @@ -6,13 +6,19 @@
-
+

-<script src="https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@main/src/widget/index.js"></script>;
-
+<script>
+document.addEventListener('DOMContentLoaded', function () {
+    const script = document.createElement('script');
+    script.src = 'https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@main/src/widget/index.js?v=' + new Date().getTime();
+    document.body.appendChild(script);
+});
+</script>;
+  
 <script>
     handleTypoReporter({ authorizationToken: '[[${wksBasicToken}]]',
     workSpaceUrl: '[[${rootUrl}]]', workSpaceId: '[[${wksId}]]'})

From a6d050ea952b3b2f5b9498f673426bb70b2241d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D0=B8=D0=BD=D0=B0=20=D0=91=D0=B5=D0=BB?=
 =?UTF-8?q?=D1=8F=D0=BA=D0=B0=D0=B5=D0=B2=D0=B0?=
 
Date: Thu, 1 Aug 2024 18:50:24 +0300
Subject: [PATCH 03/15] add console.log to widget test #283

---
 src/main/resources/templates/workspace/wks-integration.html | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/main/resources/templates/workspace/wks-integration.html b/src/main/resources/templates/workspace/wks-integration.html
index 22e7817a..2e1df302 100644
--- a/src/main/resources/templates/workspace/wks-integration.html
+++ b/src/main/resources/templates/workspace/wks-integration.html
@@ -16,9 +16,10 @@
     const script = document.createElement('script');
     script.src = 'https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@main/src/widget/index.js?v=' + new Date().getTime();
     document.body.appendChild(script);
+
+    console.log("d495bd24a1e9db08f68b63d5fbc238c4e143931c");
 });
 </script>;
-  
 <script>
     handleTypoReporter({ authorizationToken: '[[${wksBasicToken}]]',
     workSpaceUrl: '[[${rootUrl}]]', workSpaceId: '[[${wksId}]]'})

From 5b99a17fc2fac859f2ca431c2db495fd9e56d546 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D0=B8=D0=BD=D0=B0=20=D0=91=D0=B5=D0=BB?=
 =?UTF-8?q?=D1=8F=D0=BA=D0=B0=D0=B5=D0=B2=D0=B0?=
 
Date: Thu, 1 Aug 2024 20:43:12 +0300
Subject: [PATCH 04/15] fix console.log for test

---
 .../templates/workspace/wks-integration.html  |   2 -
 src/widget/index.html                         |  10 +-
 src/widget/index.js                           | 234 ++++++++++--------
 3 files changed, 142 insertions(+), 104 deletions(-)

diff --git a/src/main/resources/templates/workspace/wks-integration.html b/src/main/resources/templates/workspace/wks-integration.html
index 2e1df302..e7cc6626 100644
--- a/src/main/resources/templates/workspace/wks-integration.html
+++ b/src/main/resources/templates/workspace/wks-integration.html
@@ -16,8 +16,6 @@
     const script = document.createElement('script');
     script.src = 'https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@main/src/widget/index.js?v=' + new Date().getTime();
     document.body.appendChild(script);
-
-    console.log("d495bd24a1e9db08f68b63d5fbc238c4e143931c");
 });
 </script>;
 <script>
diff --git a/src/widget/index.html b/src/widget/index.html
index c2757d69..955c26d2 100644
--- a/src/widget/index.html
+++ b/src/widget/index.html
@@ -217,10 +217,16 @@ 

Guides

- + ; + diff --git a/src/widget/index.js b/src/widget/index.js index 451858e2..ab1d3a67 100644 --- a/src/widget/index.js +++ b/src/widget/index.js @@ -1,5 +1,7 @@ +console.log("d495bd24a1e9db08f68b63d5fbc238c4e143931c"); + const generateModalStyles = () => { - const modalStyleEl = document.createElement('style'); + const modalStyleEl = document.createElement("style"); modalStyleEl.textContent = ` #hexlet-correction-modal_modal { position: fixed; @@ -114,72 +116,81 @@ const generateModalStyles = () => { const handleBodyScroll = (modalIsOpen) => { if (modalIsOpen) { - document.body.style.overflow = 'hidden'; + document.body.style.overflow = "hidden"; } else { - document.body.style.overflow = 'auto'; + document.body.style.overflow = "auto"; } }; const generateModal = (state) => { generateModalStyles(); - const modalEl = document.createElement('div'); - modalEl.id = 'hexlet-correction-modal_modal'; - modalEl.style.display = state.modalShown ? 'block' : 'none'; + const modalEl = document.createElement("div"); + modalEl.id = "hexlet-correction-modal_modal"; + modalEl.style.display = state.modalShown ? "block" : "none"; - const divContent = document.createElement('div'); - divContent.id = 'hexlet-correction-modal_modal-content'; + const divContent = document.createElement("div"); + divContent.id = "hexlet-correction-modal_modal-content"; modalEl.append(divContent); - const divTypoReporter = document.createElement('div'); - divTypoReporter.id = 'hexlet-correction-modal_ReportTypo'; + const divTypoReporter = document.createElement("div"); + divTypoReporter.id = "hexlet-correction-modal_ReportTypo"; divContent.append(divTypoReporter); - const divHeader = document.createElement('div'); - divHeader.id = 'hexlet-correction-modal_ReportTypo-header'; - divHeader.textContent = 'Сообщите об ошибке на странице'; - - const divFirstLabel = document.createElement('div'); - divFirstLabel.classList.add('hexlet-correction-modal_ReportTypo-label'); - divFirstLabel.textContent = 'Ошибка содержится в следующем тексте:'; - - const selectedTextEl = document.createElement('div'); - selectedTextEl.id = 'hexlet-correction-modal_ReportTypo-message'; - - const inputName = document.createElement('input'); - inputName.type = 'text'; - inputName.placeholder = 'Введите свое имя или email'; - inputName.id = 'hexlet-correction-modal_ReportTypo-name'; - inputName.value = state.options.userName === null ? '' : state.options.userName; - - const commentEl = document.createElement('textarea'); - commentEl.id = 'hexlet-correction-modal_ReportTypo-comment'; - commentEl.placeholder = 'Опишите ошибку'; - - const divSecondLabel = document.createElement('div'); - divSecondLabel.classList.add('hexlet-correction-modal_ReportTypo-label'); - const strong = document.createElement('strong'); - strong.id = 'hexlet-correction-modal_question'; - strong.textContent = 'Отправить сообщение об ошибке редактору сайта?'; + const divHeader = document.createElement("div"); + divHeader.id = "hexlet-correction-modal_ReportTypo-header"; + divHeader.textContent = "Сообщите об ошибке на странице"; + + const divFirstLabel = document.createElement("div"); + divFirstLabel.classList.add("hexlet-correction-modal_ReportTypo-label"); + divFirstLabel.textContent = "Ошибка содержится в следующем тексте:"; + + const selectedTextEl = document.createElement("div"); + selectedTextEl.id = "hexlet-correction-modal_ReportTypo-message"; + + const inputName = document.createElement("input"); + inputName.type = "text"; + inputName.placeholder = "Введите свое имя или email"; + inputName.id = "hexlet-correction-modal_ReportTypo-name"; + inputName.value = + state.options.userName === null ? "" : state.options.userName; + + const commentEl = document.createElement("textarea"); + commentEl.id = "hexlet-correction-modal_ReportTypo-comment"; + commentEl.placeholder = "Опишите ошибку"; + + const divSecondLabel = document.createElement("div"); + divSecondLabel.classList.add("hexlet-correction-modal_ReportTypo-label"); + const strong = document.createElement("strong"); + strong.id = "hexlet-correction-modal_question"; + strong.textContent = "Отправить сообщение об ошибке редактору сайта?"; divSecondLabel.append(strong); - const divButtons = document.createElement('div'); - divButtons.style.textAlign = 'right'; + const divButtons = document.createElement("div"); + divButtons.style.textAlign = "right"; - const submitBtn = document.createElement('button'); - submitBtn.type = 'button'; - submitBtn.id = 'hexlet-correction-modal_ReportTypo-submit'; - submitBtn.textContent = 'Отправить'; + const submitBtn = document.createElement("button"); + submitBtn.type = "button"; + submitBtn.id = "hexlet-correction-modal_ReportTypo-submit"; + submitBtn.textContent = "Отправить"; - const cancelBtn = document.createElement('button'); - cancelBtn.type = 'button'; - cancelBtn.id = 'hexlet-correction-modal_ReportTypo-cancel'; - cancelBtn.textContent = 'Отмена'; + const cancelBtn = document.createElement("button"); + cancelBtn.type = "button"; + cancelBtn.id = "hexlet-correction-modal_ReportTypo-cancel"; + cancelBtn.textContent = "Отмена"; divButtons.append(submitBtn, cancelBtn); - divTypoReporter.append(divHeader, divFirstLabel, selectedTextEl, inputName, commentEl, divSecondLabel, divButtons); + divTypoReporter.append( + divHeader, + divFirstLabel, + selectedTextEl, + inputName, + commentEl, + divSecondLabel, + divButtons + ); - const body = document.querySelector('body'); + const body = document.querySelector("body"); body.append(modalEl); return { @@ -194,61 +205,68 @@ const generateModal = (state) => { const resetModalState = (state) => { state.modalShown = false; - state.data.reporterComment = ''; - state.data.textBeforeTypo = ''; - state.data.textTypo = ''; - state.data.textAfterTypo = ''; + state.data.reporterComment = ""; + state.data.textBeforeTypo = ""; + state.data.textTypo = ""; + state.data.textAfterTypo = ""; }; const renderModal = (elements, state) => { if (state.modalShown) { - elements.modalEl.style.display = 'block'; + elements.modalEl.style.display = "block"; const { textBeforeTypo, textTypo, textAfterTypo } = state.data; elements.selectedTextEl.innerHTML = `${textBeforeTypo}${textTypo}${textAfterTypo}`; - elements.inputName.value = state.data.reporterName !== '' ? state.data.reporterName : state.options.userName; + elements.inputName.value = + state.data.reporterName !== "" + ? state.data.reporterName + : state.options.userName; elements.commentEl.value = state.data.reporterComment; elements.commentEl.focus(); return; } - elements.modalEl.style.display = 'none'; - elements.selectedTextEl.innerHTML = ''; - elements.commentEl.value = ''; + elements.modalEl.style.display = "none"; + elements.selectedTextEl.innerHTML = ""; + elements.commentEl.value = ""; }; const sendData = (elements, state) => async (event) => { event.preventDefault(); const { value } = elements.inputName; - state.data.reporterName = value === '' ? 'Anonymous' : value; + state.data.reporterName = value === "" ? "Anonymous" : value; state.data.reporterComment = elements.commentEl.value; try { - await fetch(`${state.options.workSpaceUrl}/api/workspaces/${state.options.workSpaceId}/typos`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Basic ${state.options.authorizationToken}`, - }, - body: JSON.stringify(state.data), - }); + await fetch( + `${state.options.workSpaceUrl}/api/workspaces/${state.options.workSpaceId}/typos`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Basic ${state.options.authorizationToken}`, + }, + body: JSON.stringify(state.data), + } + ); resetModalState(state); } catch (error) { - throw new Error('Произошла ошибка:', error); + throw new Error("Произошла ошибка:", error); } }; const view = (elements, state) => { - const watch = (state, callback) => new Proxy(state, { - set(target, prop, value) { - const prevValue = target[prop]; - const result = Reflect.set(target, prop, value); - callback(prop, value, prevValue); - return result; - }, - }); + const watch = (state, callback) => + new Proxy(state, { + set(target, prop, value) { + const prevValue = target[prop]; + const result = Reflect.set(target, prop, value); + callback(prop, value, prevValue); + return result; + }, + }); const watchedState = watch(state, (path) => { switch (path) { - case 'modalShown': + case "modalShown": renderModal(elements, state); handleBodyScroll(state.modalShown); break; @@ -258,46 +276,50 @@ const view = (elements, state) => { }); return watchedState; -} +}; const isSelectionLeftToRight = (selection) => { const range = document.createRange(); range.setStart(selection.focusNode, selection.focusOffset); range.setEnd(selection.anchorNode, selection.anchorOffset); return range.collapsed; -} +}; const handleTypoReporter = (options) => { - if (!options || !options.authorizationToken && !options.workSpaceId) { - throw new Error('Для работы модуля требуется указать workSpaceId и authorizationToken'); + if (!options || (!options.authorizationToken && !options.workSpaceId)) { + throw new Error( + "Для работы модуля требуется указать workSpaceId и authorizationToken" + ); } const initialState = { modalShown: false, options: { - workSpaceUrl: 'https://hexlet-correction.herokuapp.com/api/workspaces', + workSpaceUrl: "https://hexlet-correction.herokuapp.com/api/workspaces", userName: null, ...options, }, data: { - pageUrl: '', - reporterName: '', - reporterComment: '', - textBeforeTypo: '', - textTypo: '', - textAfterTypo: '', + pageUrl: "", + reporterName: "", + reporterComment: "", + textBeforeTypo: "", + textTypo: "", + textAfterTypo: "", }, }; const elements = generateModal(initialState); const state = view(elements, initialState); - document.addEventListener('keydown', (event) => { + console.log("Widget is initialized"); + + document.addEventListener("keydown", (event) => { const selection = window.getSelection(); if (selection.isCollapsed || state.modalShown) { return; } - if (event.ctrlKey && event.key === 'Enter') { + if (event.ctrlKey && event.key === "Enter") { state.data.pageUrl = window.location.href; const { anchorNode } = selection; @@ -307,33 +329,45 @@ const handleTypoReporter = (options) => { const maxLength = 50; state.data.textTypo = selection.toString(); - if(isSelectionLeftToRight(selection)) { + if (isSelectionLeftToRight(selection)) { const start = Math.max(anchorOffset - maxLength, 0); const end = Math.min(focusOffset + maxLength, anchorNode.length); - state.data.textBeforeTypo = anchorNode.textContent.substring(start, anchorOffset); - state.data.textAfterTypo = anchorNode.substringData(focusOffset, end - focusOffset); + state.data.textBeforeTypo = anchorNode.textContent.substring( + start, + anchorOffset + ); + state.data.textAfterTypo = anchorNode.substringData( + focusOffset, + end - focusOffset + ); } else { - const start = Math.max(focusOffset - maxLength, 0); + const start = Math.max(focusOffset - maxLength, 0); const end = Math.min(anchorOffset + maxLength, anchorNode.length); - state.data.textBeforeTypo = anchorNode.textContent.substring(start, focusOffset); - state.data.textAfterTypo = anchorNode.substringData(anchorOffset, end - anchorOffset); + state.data.textBeforeTypo = anchorNode.textContent.substring( + start, + focusOffset + ); + state.data.textAfterTypo = anchorNode.substringData( + anchorOffset, + end - anchorOffset + ); } state.modalShown = true; } }); - elements.submitBtn.addEventListener('click', sendData(elements, state)); - elements.cancelBtn.addEventListener('click', () => resetModalState(state)); + elements.submitBtn.addEventListener("click", sendData(elements, state)); + elements.cancelBtn.addEventListener("click", () => resetModalState(state)); - elements.modalEl.addEventListener('click', (event) => { + elements.modalEl.addEventListener("click", (event) => { if (event.target === elements.modalEl) { resetModalState(state); } }); - elements.modalEl.addEventListener('keydown', (event) => { - if (state.modalShown && event.key === 'Escape') { + elements.modalEl.addEventListener("keydown", (event) => { + if (state.modalShown && event.key === "Escape") { resetModalState(state); } }); From ebe392dc9b0769da74e771af664db85133423117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D0=B8=D0=BD=D0=B0=20=D0=91=D0=B5=D0=BB?= =?UTF-8?q?=D1=8F=D0=BA=D0=B0=D0=B5=D0=B2=D0=B0?= Date: Fri, 2 Aug 2024 15:43:41 +0300 Subject: [PATCH 05/15] fix console.log & quotes --- src/widget/index.js | 211 +++++++++++++++++++------------------------- 1 file changed, 89 insertions(+), 122 deletions(-) diff --git a/src/widget/index.js b/src/widget/index.js index ab1d3a67..c189ce69 100644 --- a/src/widget/index.js +++ b/src/widget/index.js @@ -1,7 +1,5 @@ -console.log("d495bd24a1e9db08f68b63d5fbc238c4e143931c"); - const generateModalStyles = () => { - const modalStyleEl = document.createElement("style"); + const modalStyleEl = document.createElement('style'); modalStyleEl.textContent = ` #hexlet-correction-modal_modal { position: fixed; @@ -116,81 +114,72 @@ const generateModalStyles = () => { const handleBodyScroll = (modalIsOpen) => { if (modalIsOpen) { - document.body.style.overflow = "hidden"; + document.body.style.overflow = 'hidden'; } else { - document.body.style.overflow = "auto"; + document.body.style.overflow = 'auto'; } }; const generateModal = (state) => { generateModalStyles(); - const modalEl = document.createElement("div"); - modalEl.id = "hexlet-correction-modal_modal"; - modalEl.style.display = state.modalShown ? "block" : "none"; + const modalEl = document.createElement('div'); + modalEl.id = 'hexlet-correction-modal_modal'; + modalEl.style.display = state.modalShown ? 'block' : 'none'; - const divContent = document.createElement("div"); - divContent.id = "hexlet-correction-modal_modal-content"; + const divContent = document.createElement('div'); + divContent.id = 'hexlet-correction-modal_modal-content'; modalEl.append(divContent); - const divTypoReporter = document.createElement("div"); - divTypoReporter.id = "hexlet-correction-modal_ReportTypo"; + const divTypoReporter = document.createElement('div'); + divTypoReporter.id = 'hexlet-correction-modal_ReportTypo'; divContent.append(divTypoReporter); - const divHeader = document.createElement("div"); - divHeader.id = "hexlet-correction-modal_ReportTypo-header"; - divHeader.textContent = "Сообщите об ошибке на странице"; - - const divFirstLabel = document.createElement("div"); - divFirstLabel.classList.add("hexlet-correction-modal_ReportTypo-label"); - divFirstLabel.textContent = "Ошибка содержится в следующем тексте:"; - - const selectedTextEl = document.createElement("div"); - selectedTextEl.id = "hexlet-correction-modal_ReportTypo-message"; - - const inputName = document.createElement("input"); - inputName.type = "text"; - inputName.placeholder = "Введите свое имя или email"; - inputName.id = "hexlet-correction-modal_ReportTypo-name"; - inputName.value = - state.options.userName === null ? "" : state.options.userName; - - const commentEl = document.createElement("textarea"); - commentEl.id = "hexlet-correction-modal_ReportTypo-comment"; - commentEl.placeholder = "Опишите ошибку"; - - const divSecondLabel = document.createElement("div"); - divSecondLabel.classList.add("hexlet-correction-modal_ReportTypo-label"); - const strong = document.createElement("strong"); - strong.id = "hexlet-correction-modal_question"; - strong.textContent = "Отправить сообщение об ошибке редактору сайта?"; + const divHeader = document.createElement('div'); + divHeader.id = 'hexlet-correction-modal_ReportTypo-header'; + divHeader.textContent = 'Сообщите об ошибке на странице'; + + const divFirstLabel = document.createElement('div'); + divFirstLabel.classList.add('hexlet-correction-modal_ReportTypo-label'); + divFirstLabel.textContent = 'Ошибка содержится в следующем тексте:'; + + const selectedTextEl = document.createElement('div'); + selectedTextEl.id = 'hexlet-correction-modal_ReportTypo-message'; + + const inputName = document.createElement('input'); + inputName.type = 'text'; + inputName.placeholder = 'Введите свое имя или email'; + inputName.id = 'hexlet-correction-modal_ReportTypo-name'; + inputName.value = state.options.userName === null ? '' : state.options.userName; + + const commentEl = document.createElement('textarea'); + commentEl.id = 'hexlet-correction-modal_ReportTypo-comment'; + commentEl.placeholder = 'Опишите ошибку'; + + const divSecondLabel = document.createElement('div'); + divSecondLabel.classList.add('hexlet-correction-modal_ReportTypo-label'); + const strong = document.createElement('strong'); + strong.id = 'hexlet-correction-modal_question'; + strong.textContent = 'Отправить сообщение об ошибке редактору сайта?'; divSecondLabel.append(strong); - const divButtons = document.createElement("div"); - divButtons.style.textAlign = "right"; + const divButtons = document.createElement('div'); + divButtons.style.textAlign = 'right'; - const submitBtn = document.createElement("button"); - submitBtn.type = "button"; - submitBtn.id = "hexlet-correction-modal_ReportTypo-submit"; - submitBtn.textContent = "Отправить"; + const submitBtn = document.createElement('button'); + submitBtn.type = 'button'; + submitBtn.id = 'hexlet-correction-modal_ReportTypo-submit'; + submitBtn.textContent = 'Отправить'; - const cancelBtn = document.createElement("button"); - cancelBtn.type = "button"; - cancelBtn.id = "hexlet-correction-modal_ReportTypo-cancel"; - cancelBtn.textContent = "Отмена"; + const cancelBtn = document.createElement('button'); + cancelBtn.type = 'button'; + cancelBtn.id = 'hexlet-correction-modal_ReportTypo-cancel'; + cancelBtn.textContent = 'Отмена'; divButtons.append(submitBtn, cancelBtn); - divTypoReporter.append( - divHeader, - divFirstLabel, - selectedTextEl, - inputName, - commentEl, - divSecondLabel, - divButtons - ); + divTypoReporter.append(divHeader, divFirstLabel, selectedTextEl, inputName, commentEl, divSecondLabel, divButtons); - const body = document.querySelector("body"); + const body = document.querySelector('body'); body.append(modalEl); return { @@ -205,57 +194,50 @@ const generateModal = (state) => { const resetModalState = (state) => { state.modalShown = false; - state.data.reporterComment = ""; - state.data.textBeforeTypo = ""; - state.data.textTypo = ""; - state.data.textAfterTypo = ""; + state.data.reporterComment = ''; + state.data.textBeforeTypo = ''; + state.data.textTypo = ''; + state.data.textAfterTypo = ''; }; const renderModal = (elements, state) => { if (state.modalShown) { - elements.modalEl.style.display = "block"; + elements.modalEl.style.display = 'block'; const { textBeforeTypo, textTypo, textAfterTypo } = state.data; elements.selectedTextEl.innerHTML = `${textBeforeTypo}${textTypo}${textAfterTypo}`; - elements.inputName.value = - state.data.reporterName !== "" - ? state.data.reporterName - : state.options.userName; + elements.inputName.value = state.data.reporterName !== '' ? state.data.reporterName : state.options.userName; elements.commentEl.value = state.data.reporterComment; elements.commentEl.focus(); return; } - elements.modalEl.style.display = "none"; - elements.selectedTextEl.innerHTML = ""; - elements.commentEl.value = ""; + elements.modalEl.style.display = 'none'; + elements.selectedTextEl.innerHTML = ''; + elements.commentEl.value = ''; }; const sendData = (elements, state) => async (event) => { event.preventDefault(); const { value } = elements.inputName; - state.data.reporterName = value === "" ? "Anonymous" : value; + state.data.reporterName = value === '' ? 'Anonymous' : value; state.data.reporterComment = elements.commentEl.value; try { - await fetch( - `${state.options.workSpaceUrl}/api/workspaces/${state.options.workSpaceId}/typos`, - { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Basic ${state.options.authorizationToken}`, - }, - body: JSON.stringify(state.data), - } - ); + await fetch(`${state.options.workSpaceUrl}/api/workspaces/${state.options.workSpaceId}/typos`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Basic ${state.options.authorizationToken}`, + }, + body: JSON.stringify(state.data), + }); resetModalState(state); } catch (error) { - throw new Error("Произошла ошибка:", error); + throw new Error('Произошла ошибка:', error); } }; const view = (elements, state) => { - const watch = (state, callback) => - new Proxy(state, { + const watch = (state, callback) => new Proxy(state, { set(target, prop, value) { const prevValue = target[prop]; const result = Reflect.set(target, prop, value); @@ -266,7 +248,7 @@ const view = (elements, state) => { const watchedState = watch(state, (path) => { switch (path) { - case "modalShown": + case 'modalShown': renderModal(elements, state); handleBodyScroll(state.modalShown); break; @@ -286,40 +268,37 @@ const isSelectionLeftToRight = (selection) => { }; const handleTypoReporter = (options) => { + console.log('a6d050ea952b3b2f5b9498f673426bb70b2241d4'); if (!options || (!options.authorizationToken && !options.workSpaceId)) { - throw new Error( - "Для работы модуля требуется указать workSpaceId и authorizationToken" - ); + throw new Error('Для работы модуля требуется указать workSpaceId и authorizationToken'); } const initialState = { modalShown: false, options: { - workSpaceUrl: "https://hexlet-correction.herokuapp.com/api/workspaces", + workSpaceUrl: 'https://hexlet-correction.herokuapp.com/api/workspaces', userName: null, ...options, }, data: { - pageUrl: "", - reporterName: "", - reporterComment: "", - textBeforeTypo: "", - textTypo: "", - textAfterTypo: "", + pageUrl: '', + reporterName: '', + reporterComment: '', + textBeforeTypo: '', + textTypo: '', + textAfterTypo: '', }, }; const elements = generateModal(initialState); const state = view(elements, initialState); - console.log("Widget is initialized"); - - document.addEventListener("keydown", (event) => { + document.addEventListener('keydown', (event) => { const selection = window.getSelection(); if (selection.isCollapsed || state.modalShown) { return; } - if (event.ctrlKey && event.key === "Enter") { + if (event.ctrlKey && event.key === 'Enter') { state.data.pageUrl = window.location.href; const { anchorNode } = selection; @@ -332,42 +311,30 @@ const handleTypoReporter = (options) => { if (isSelectionLeftToRight(selection)) { const start = Math.max(anchorOffset - maxLength, 0); const end = Math.min(focusOffset + maxLength, anchorNode.length); - state.data.textBeforeTypo = anchorNode.textContent.substring( - start, - anchorOffset - ); - state.data.textAfterTypo = anchorNode.substringData( - focusOffset, - end - focusOffset - ); + state.data.textBeforeTypo = anchorNode.textContent.substring(start, anchorOffset); + state.data.textAfterTypo = anchorNode.substringData(focusOffset, end - focusOffset); } else { const start = Math.max(focusOffset - maxLength, 0); const end = Math.min(anchorOffset + maxLength, anchorNode.length); - state.data.textBeforeTypo = anchorNode.textContent.substring( - start, - focusOffset - ); - state.data.textAfterTypo = anchorNode.substringData( - anchorOffset, - end - anchorOffset - ); + state.data.textBeforeTypo = anchorNode.textContent.substring(start, focusOffset); + state.data.textAfterTypo = anchorNode.substringData(anchorOffset, end - anchorOffset); } state.modalShown = true; } }); - elements.submitBtn.addEventListener("click", sendData(elements, state)); - elements.cancelBtn.addEventListener("click", () => resetModalState(state)); + elements.submitBtn.addEventListener('click', sendData(elements, state)); + elements.cancelBtn.addEventListener('click', () => resetModalState(state)); - elements.modalEl.addEventListener("click", (event) => { + elements.modalEl.addEventListener('click', (event) => { if (event.target === elements.modalEl) { resetModalState(state); } }); - elements.modalEl.addEventListener("keydown", (event) => { - if (state.modalShown && event.key === "Escape") { + elements.modalEl.addEventListener('keydown', (event) => { + if (state.modalShown && event.key === 'Escape') { resetModalState(state); } }); From 13ccb4b8645520f3a4eeaae438ddc450085d3ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D0=B8=D0=BD=D0=B0=20=D0=91=D0=B5=D0=BB?= =?UTF-8?q?=D1=8F=D0=BA=D0=B0=D0=B5=D0=B2=D0=B0?= Date: Fri, 2 Aug 2024 16:05:25 +0300 Subject: [PATCH 06/15] remove new script from index.html --- src/widget/index.html | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/widget/index.html b/src/widget/index.html index 955c26d2..c2757d69 100644 --- a/src/widget/index.html +++ b/src/widget/index.html @@ -217,16 +217,10 @@

Guides

- ; + + From c09abb4553c41bbe54dcbd3d2bac3b1a9ef9d437 Mon Sep 17 00:00:00 2001 From: Nikolay Gagarinov Date: Fri, 2 Aug 2024 20:21:29 +0500 Subject: [PATCH 07/15] Update index.html --- src/widget/index.html | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/widget/index.html b/src/widget/index.html index c2757d69..545cf090 100644 --- a/src/widget/index.html +++ b/src/widget/index.html @@ -217,10 +217,16 @@

Guides

- - +; + From 73f615078a2936ba4488c5e2da3dab3c574dc02d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=BE=D0=BB=D0=B8=D0=BD=D0=B0=20=D0=91=D0=B5=D0=BB?= =?UTF-8?q?=D1=8F=D0=BA=D0=B0=D0=B5=D0=B2=D0=B0?= Date: Mon, 5 Aug 2024 17:42:24 +0300 Subject: [PATCH 08/15] update rework the script connection - use greedy loading #283 --- .../templates/workspace/wks-integration.html | 29 ++++++++++++------- src/widget/index.js | 2 +- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/main/resources/templates/workspace/wks-integration.html b/src/main/resources/templates/workspace/wks-integration.html index e7cc6626..0d070878 100644 --- a/src/main/resources/templates/workspace/wks-integration.html +++ b/src/main/resources/templates/workspace/wks-integration.html @@ -12,18 +12,27 @@

 <script>
+function loadScript(src, callback) {
+  const body = document.querySelector('body')
+  const script = document.createElement('script');
+  script.src = src;
+  script.onload = callback;
+  body.appendChild(script);
+};
+
 document.addEventListener('DOMContentLoaded', function () {
-    const script = document.createElement('script');
-    script.src = 'https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@main/src/widget/index.js?v=' + new Date().getTime();
-    document.body.appendChild(script);
+  const scriptSrc = 'https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@main/src/widget/index.js?v=' + new Date().getTime();
+  loadScript(scriptSrc, function () {
+    handleTypoReporter({ 
+      authorizationToken: '[[${wksBasicToken}]]',
+      workSpaceUrl: '[[${rootUrl}]]', 
+      workSpaceId: '[[${wksId}]]'})
+  });
 });
-</script>;
-<script>
-    handleTypoReporter({ authorizationToken: '[[${wksBasicToken}]]',
-    workSpaceUrl: '[[${rootUrl}]]', workSpaceId: '[[${wksId}]]'})
-</script>
-
-
+</script> + + +
diff --git a/src/widget/index.js b/src/widget/index.js index c189ce69..61e22abc 100644 --- a/src/widget/index.js +++ b/src/widget/index.js @@ -268,7 +268,7 @@ const isSelectionLeftToRight = (selection) => { }; const handleTypoReporter = (options) => { - console.log('a6d050ea952b3b2f5b9498f673426bb70b2241d4'); + console.log('Script loaded:', new Date().getTime()); if (!options || (!options.authorizationToken && !options.workSpaceId)) { throw new Error('Для работы модуля требуется указать workSpaceId и authorizationToken'); } From 813a17e3e15d0d7adde1e1875a9034de5ee6e212 Mon Sep 17 00:00:00 2001 From: Nikolay Gagarinov Date: Thu, 8 Aug 2024 23:18:11 +0500 Subject: [PATCH 09/15] fix demo --- src/widget/index.html | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/widget/index.html b/src/widget/index.html index 545cf090..29ee1ed6 100644 --- a/src/widget/index.html +++ b/src/widget/index.html @@ -216,17 +216,26 @@

Guides

Created by the Bootstrap team · © 2023 - -; - + + From ab2a2698cf900c2f6792980599d166177aca6d3e Mon Sep 17 00:00:00 2001 From: Nikolay Gagarinov Date: Thu, 8 Aug 2024 23:18:57 +0500 Subject: [PATCH 10/15] update console.log --- src/widget/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widget/index.js b/src/widget/index.js index 61e22abc..e22298b0 100644 --- a/src/widget/index.js +++ b/src/widget/index.js @@ -268,7 +268,7 @@ const isSelectionLeftToRight = (selection) => { }; const handleTypoReporter = (options) => { - console.log('Script loaded:', new Date().getTime()); + console.log('commit 813a17e3e15d0d7adde1e1875a9034de5ee6e212'); if (!options || (!options.authorizationToken && !options.workSpaceId)) { throw new Error('Для работы модуля требуется указать workSpaceId и authorizationToken'); } From 6ced041d2df54c4da87bb294b926e7ffce7a310d Mon Sep 17 00:00:00 2001 From: Nikolay Gagarinov Date: Thu, 8 Aug 2024 23:26:24 +0500 Subject: [PATCH 11/15] fix load latest --- src/main/resources/templates/workspace/wks-integration.html | 6 +++--- src/widget/index.html | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/templates/workspace/wks-integration.html b/src/main/resources/templates/workspace/wks-integration.html index 0d070878..190249e8 100644 --- a/src/main/resources/templates/workspace/wks-integration.html +++ b/src/main/resources/templates/workspace/wks-integration.html @@ -21,11 +21,11 @@ }; document.addEventListener('DOMContentLoaded', function () { - const scriptSrc = 'https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@main/src/widget/index.js?v=' + new Date().getTime(); + const scriptSrc = 'https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@latest/src/widget/index.js?v=' + new Date().getTime(); loadScript(scriptSrc, function () { - handleTypoReporter({ + handleTypoReporter({ authorizationToken: '[[${wksBasicToken}]]', - workSpaceUrl: '[[${rootUrl}]]', + workSpaceUrl: '[[${rootUrl}]]', workSpaceId: '[[${wksId}]]'}) }); }); diff --git a/src/widget/index.html b/src/widget/index.html index 29ee1ed6..03c31ef3 100644 --- a/src/widget/index.html +++ b/src/widget/index.html @@ -227,7 +227,7 @@

Guides

}; document.addEventListener('DOMContentLoaded', function () { - const scriptSrc = 'https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@main/src/widget/index.js?v=' + new Date().getTime(); + const scriptSrc = 'https://cdn.jsdelivr.net/gh/hexlet/hexlet-correction@latest/src/widget/index.js?v=' + new Date().getTime(); loadScript(scriptSrc, function () { handleTypoReporter({ authorizationToken: 'MjQyOmVlYTZkMWE1LTNkMGQtNDg1Yi04OGMwLWVkOGU1YTRlOGZjMA==', From 03f03dba6ed035950bd6c71074fdef3f7e294f68 Mon Sep 17 00:00:00 2001 From: Nikolay Gagarinov Date: Fri, 9 Aug 2024 23:36:48 +0500 Subject: [PATCH 12/15] Update index.js --- src/widget/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widget/index.js b/src/widget/index.js index e22298b0..83c6db5d 100644 --- a/src/widget/index.js +++ b/src/widget/index.js @@ -268,7 +268,7 @@ const isSelectionLeftToRight = (selection) => { }; const handleTypoReporter = (options) => { - console.log('commit 813a17e3e15d0d7adde1e1875a9034de5ee6e212'); + console.log('commit 6ced041'); if (!options || (!options.authorizationToken && !options.workSpaceId)) { throw new Error('Для работы модуля требуется указать workSpaceId и authorizationToken'); } From 8b6a54a163238b7ed7cf553aaa9daed18672714d Mon Sep 17 00:00:00 2001 From: FC-LinuxMachine Date: Tue, 13 Aug 2024 21:48:55 +0700 Subject: [PATCH 13/15] fixes #291 Bug: User is registered with an incorrectly confirmed Password --- .../service/dto/FieldMatchConsiderCase.java | 21 ++--------- .../web/model/SignupAccountModel.java | 2 +- src/main/resources/messages_en.properties | 1 + src/main/resources/messages_ru.properties | 1 + .../typoreporter/web/SignupControllerIT.java | 37 +++++++++++++++++-- 5 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/main/java/io/hexlet/typoreporter/service/dto/FieldMatchConsiderCase.java b/src/main/java/io/hexlet/typoreporter/service/dto/FieldMatchConsiderCase.java index 3e3b489f..211f42d1 100644 --- a/src/main/java/io/hexlet/typoreporter/service/dto/FieldMatchConsiderCase.java +++ b/src/main/java/io/hexlet/typoreporter/service/dto/FieldMatchConsiderCase.java @@ -3,14 +3,11 @@ import jakarta.validation.Constraint; import jakarta.validation.Payload; -import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - /** * Validation annotation to validate that 2 fields have the same value. * An array of fields and their matching confirmation fields can be supplied. @@ -27,6 +24,8 @@ * message = "The password and it confirmation must match")} */ @Constraint(validatedBy = FieldMatchConsiderCaseValidator.class) +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) public @interface FieldMatchConsiderCase { String message() default "The {first} and {second} fields must be equal"; @@ -45,16 +44,4 @@ */ String second(); - /** - * Defines several @FieldMatch annotations on the same element - * - * @see FieldMatchConsiderCase - */ - @Target({TYPE, ANNOTATION_TYPE}) - @Retention(RUNTIME) - @Documented - @interface List { - - FieldMatchConsiderCase[] value(); - } } diff --git a/src/main/java/io/hexlet/typoreporter/web/model/SignupAccountModel.java b/src/main/java/io/hexlet/typoreporter/web/model/SignupAccountModel.java index b475a10b..16b51637 100644 --- a/src/main/java/io/hexlet/typoreporter/web/model/SignupAccountModel.java +++ b/src/main/java/io/hexlet/typoreporter/web/model/SignupAccountModel.java @@ -19,7 +19,7 @@ @FieldMatchConsiderCase( first = "password", second = "confirmPassword", - message = "The password and it confirmation must match") + message = "{alert.passwords-dont-match}") @ToString public class SignupAccountModel { diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 892b32df..8b1b2151 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -104,3 +104,4 @@ btn.delete-from-wks=Delete from workspace alert.password-wrong-format=Password must be between 8 and 20 characters \ and contain only latin letters, digits and symbols ~`!@#$%^&*()_-+={[}]|\:;"'<,>.?/ +alert.passwords-dont-match=Confirmation does not match the password diff --git a/src/main/resources/messages_ru.properties b/src/main/resources/messages_ru.properties index 65312c97..7da709f7 100644 --- a/src/main/resources/messages_ru.properties +++ b/src/main/resources/messages_ru.properties @@ -102,3 +102,4 @@ text.wks-delete-confirm=Удалить пространство? alert.password-wrong-format=Пароль должен быть от 8 до 20 символов\ \ и содержать только буквы латинского алфавита,\ \ цифры и символы ~`!@#$%^&*()_-+={[}]|\:;"'<,>.?/ +alert.passwords-dont-match=Подтверждение не совпадает с паролем diff --git a/src/test/java/io/hexlet/typoreporter/web/SignupControllerIT.java b/src/test/java/io/hexlet/typoreporter/web/SignupControllerIT.java index d0b5ce1b..5f9fdcc6 100644 --- a/src/test/java/io/hexlet/typoreporter/web/SignupControllerIT.java +++ b/src/test/java/io/hexlet/typoreporter/web/SignupControllerIT.java @@ -5,24 +5,26 @@ import io.hexlet.typoreporter.repository.AccountRepository; import io.hexlet.typoreporter.test.DBUnitEnumPostgres; import io.hexlet.typoreporter.web.model.SignupAccountModel; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.web.servlet.MockMvc; import org.springframework.transaction.annotation.Transactional; -import org.testcontainers.junit.jupiter.Testcontainers; -import org.testcontainers.junit.jupiter.Container; import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; import static com.github.database.rider.core.api.configuration.Orthography.LOWERCASE; +import static io.hexlet.typoreporter.test.Constraints.POSTGRES_IMAGE; import static io.hexlet.typoreporter.test.factory.EntitiesFactory.ACCOUNT_INCORRECT_EMAIL; +import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.assertj.core.api.Assertions.assertThat; -import static io.hexlet.typoreporter.test.Constraints.POSTGRES_IMAGE; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @SpringBootTest @@ -66,6 +68,14 @@ static void datasourceProperties(DynamicPropertyRegistry registry) { "another_password", "another_password", "another_firstName", "another_lastName"); + private static ResourceBundleMessageSource source; + + @BeforeAll + static void init() { + source = new ResourceBundleMessageSource(); + source.setBasename("messages_en"); + } + @Test void createAccountWithIgnoreEmailCase() throws Exception { assertThat(accountRepository.count()).isEqualTo(0L); @@ -140,4 +150,23 @@ void signupInAccountWithBadEmail() throws Exception { var body = response.getResponse().getContentAsString(); assertThat(body).contains(String.format("The email "%s" is not valid", ACCOUNT_INCORRECT_EMAIL)); } + + @Test + void signupInPasswordsDontMatch() throws Exception { + model.setConfirmPassword("WrongPassword123"); + var response = mockMvc.perform(post("/signup") + .param("username", model.getUsername()) + .param("email", model.getEmail()) + .param("password", model.getPassword()) + .param("confirmPassword", model.getConfirmPassword()) + .param("firstName", model.getFirstName()) + .param("lastName", model.getLastName()) + .with(csrf())) + .andReturn(); + var body = response.getResponse().getContentAsString(); + + assertThat(body).contains(source.getMessage("alert.passwords-dont-match", null, null)); + + } + } From aca0992bde58427b280a69eb1b69ada7f15e5ff9 Mon Sep 17 00:00:00 2001 From: ymirotvorenie Date: Wed, 14 Aug 2024 16:47:31 +0700 Subject: [PATCH 14/15] Fix Issue#293. Add russian translate to email-placeholder at workspace->users --- src/main/resources/messages_en.properties | 1 + src/main/resources/messages_ru.properties | 1 + src/main/resources/templates/workspace/wks-users.html | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 892b32df..d370eba2 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -66,6 +66,7 @@ wks.placeholder.descr=Workspace Description wks.info=Info wks.typos=Typos wks.users=Users +wks.users.email-placeholder=Enter user email. For example: hexlet@gmail.com wks.settings=Settings wks.urls=URLs wks.integration=Integration diff --git a/src/main/resources/messages_ru.properties b/src/main/resources/messages_ru.properties index 65312c97..351633c8 100644 --- a/src/main/resources/messages_ru.properties +++ b/src/main/resources/messages_ru.properties @@ -71,6 +71,7 @@ wks.placeholder.descr=Описание Пространства wks.info=Информация wks.typos=Опечатки wks.users=Пользователи +wks.users.email-placeholder=Введите адрес электронной почты пользователя. Например: hexlet@gmail.com wks.settings=Настройки wks.urls=Домены wks.integration=Интеграция diff --git a/src/main/resources/templates/workspace/wks-users.html b/src/main/resources/templates/workspace/wks-users.html index 642f6b0b..3e5f68f3 100644 --- a/src/main/resources/templates/workspace/wks-users.html +++ b/src/main/resources/templates/workspace/wks-users.html @@ -24,7 +24,7 @@
From e76b3abe65b3573bb5ac60a2edde9eb4395eff1f Mon Sep 17 00:00:00 2001 From: FC-LinuxMachine Date: Wed, 21 Aug 2024 16:46:14 +0700 Subject: [PATCH 15/15] #254 updated test verification that the user hasn`t added to DB --- .../java/io/hexlet/typoreporter/web/SignupControllerIT.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/io/hexlet/typoreporter/web/SignupControllerIT.java b/src/test/java/io/hexlet/typoreporter/web/SignupControllerIT.java index 5f9fdcc6..1393bfe5 100644 --- a/src/test/java/io/hexlet/typoreporter/web/SignupControllerIT.java +++ b/src/test/java/io/hexlet/typoreporter/web/SignupControllerIT.java @@ -164,8 +164,10 @@ void signupInPasswordsDontMatch() throws Exception { .with(csrf())) .andReturn(); var body = response.getResponse().getContentAsString(); + var result = accountRepository.findAccountByEmail(model.getEmail().toLowerCase()); assertThat(body).contains(source.getMessage("alert.passwords-dont-match", null, null)); + assertThat(result).isEmpty(); }