{
it('renders anonymous user', () => {
const wrapper = Wrapper()
- expect(wrapper.text()).not.toMatch('Tilda Swinton')
- expect(wrapper.text()).toMatch('Anonymus')
+ expect(wrapper.text()).toBe('')
+ expect(mocks.$t).toHaveBeenCalledWith('profile.userAnonym')
})
describe('given an user', () => {
@@ -65,7 +65,7 @@ describe('User', () => {
it('renders user name', () => {
const wrapper = Wrapper()
- expect(wrapper.text()).not.toMatch('Anonymous')
+ expect(mocks.$t).not.toHaveBeenCalledWith('profile.userAnonym')
expect(wrapper.text()).toMatch('Tilda Swinton')
})
@@ -77,7 +77,7 @@ describe('User', () => {
it('renders anonymous user', () => {
const wrapper = Wrapper()
expect(wrapper.text()).not.toMatch('Tilda Swinton')
- expect(wrapper.text()).toMatch('Anonymus')
+ expect(mocks.$t).toHaveBeenCalledWith('profile.userAnonym')
})
describe('current user is a moderator', () => {
diff --git a/webapp/components/comments/CommentForm/index.vue b/webapp/components/comments/CommentForm/index.vue
index d59314e07..fedd8a884 100644
--- a/webapp/components/comments/CommentForm/index.vue
+++ b/webapp/components/comments/CommentForm/index.vue
@@ -97,8 +97,8 @@ export default {
})
.then(res => {
this.loading = false
- this.$root.$emit('refetchPostComments', res.data.CreateComment)
- this.$refs.editor.clear()
+ this.$root.$emit('refetchPostComments')
+ this.clear()
this.$toast.success(this.$t('post.comment.submitted'))
this.disabled = false
})
diff --git a/webapp/components/comments/CommentForm/spec.js b/webapp/components/comments/CommentForm/spec.js
new file mode 100644
index 000000000..511f76c1d
--- /dev/null
+++ b/webapp/components/comments/CommentForm/spec.js
@@ -0,0 +1,92 @@
+import { config, mount, createLocalVue, createWrapper } from '@vue/test-utils'
+import CommentForm from './index.vue'
+import Vue from 'vue'
+import Styleguide from '@human-connection/styleguide'
+
+const localVue = createLocalVue()
+
+localVue.use(Styleguide)
+
+config.stubs['no-ssr'] = '
'
+
+describe('CommentForm.vue', () => {
+ let mocks
+ let wrapper
+ let propsData
+ let cancelBtn
+ let cancelMethodSpy
+
+ beforeEach(() => {
+ ;(mocks = {
+ $t: jest.fn(),
+ $apollo: {
+ mutate: jest
+ .fn()
+ .mockResolvedValueOnce({
+ data: { CreateComment: { contentExcerpt: 'this is a comment' } }
+ })
+ .mockRejectedValue({ message: 'Ouch!' })
+ },
+ $toast: {
+ error: jest.fn(),
+ success: jest.fn()
+ }
+ }),
+ (propsData = {
+ post: { id: 1 }
+ })
+ })
+
+ describe('mount', () => {
+ const Wrapper = () => {
+ return mount(CommentForm, { mocks, localVue, propsData })
+ }
+
+ beforeEach(() => {
+ wrapper = Wrapper()
+ cancelMethodSpy = jest.spyOn(wrapper.vm, 'clear')
+ })
+
+ it('calls the apollo mutation when form is submitted', async () => {
+ wrapper.vm.updateEditorContent('this is a comment')
+ await wrapper.find('form').trigger('submit')
+ expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
+ })
+
+ it('calls clear method when the cancel button is clicked', () => {
+ wrapper.vm.updateEditorContent('ok')
+ cancelBtn = wrapper.find('.cancelBtn')
+ cancelBtn.trigger('click')
+ expect(cancelMethodSpy).toHaveBeenCalledTimes(1)
+ })
+
+ describe('mutation resolves', () => {
+ beforeEach(async () => {
+ wrapper.vm.updateEditorContent('this is a comment')
+ wrapper.find('form').trigger('submit')
+ })
+
+ it('shows a success toaster', async () => {
+ await mocks.$apollo.mutate
+ expect(mocks.$toast.success).toHaveBeenCalledTimes(1)
+ })
+
+ it('clears the editor', () => {
+ expect(cancelMethodSpy).toHaveBeenCalledTimes(1)
+ })
+
+ it('emits a method call with the returned comment', () => {
+ const rootWrapper = createWrapper(wrapper.vm.$root)
+ expect(rootWrapper.emitted().refetchPostComments.length).toEqual(1)
+ })
+
+ describe('mutation fails', () => {
+ it('shows the error toaster', async () => {
+ await wrapper.find('form').trigger('submit')
+ await mocks.$apollo.mutate
+ expect(mocks.$toast.error).toHaveBeenCalledTimes(1)
+ })
+ })
+ })
+ })
+})
diff --git a/webapp/layouts/default.vue b/webapp/layouts/default.vue
index d4ac731e3..f34b02899 100644
--- a/webapp/layouts/default.vue
+++ b/webapp/layouts/default.vue
@@ -48,7 +48,7 @@
@@ -146,6 +149,10 @@ export default {
quickSearchResults: 'search/quickResults',
quickSearchPending: 'search/quickPending'
}),
+ userName() {
+ const { name } = this.user || {}
+ return name || this.$t('profile.userAnonym')
+ },
routes() {
if (!this.user.slug) {
return []
diff --git a/webapp/locales/de.json b/webapp/locales/de.json
index 14e709866..96f87cd9d 100644
--- a/webapp/locales/de.json
+++ b/webapp/locales/de.json
@@ -21,11 +21,12 @@
"following": "Folgt",
"shouted": "Empfohlen",
"commented": "Kommentiert",
+ "userAnonym": "Anonymus",
"socialMedia": "Wo sonst finde ich"
},
"notifications": {
"menu": {
- "mentioned": "hat dich in einem Beitrag erwähnt"
+ "mentioned": "hat dich in einem Beitrag erwähnt"
}
},
"search": {
@@ -38,14 +39,29 @@
"data": {
"name": "Deine Daten",
"labelName": "Dein Name",
+ "namePlaceholder": "Petra Lustig",
"labelCity": "Deine Stadt oder Region",
- "labelBio": "Über dich"
+ "labelBio": "Über dich",
+ "success": "Deine Daten wurden erfolgreich aktualisiert!"
},
"security": {
"name": "Sicherheit",
"change-password": {
"button": "Passwort ändern",
- "success": "Passwort erfolgreich geändert!"
+ "success": "Passwort erfolgreich geändert!",
+ "label-old-password": "Dein altes Passwort",
+ "label-new-password": "Dein neues Passwort",
+ "label-new-password-confirm": "Bestätige Dein neues Passwort",
+ "message-old-password-required": "Gebe dein altes Passwort ein",
+ "message-new-password-required": "Gebe ein neues Passwort ein",
+ "message-new-password-confirm-required": "Bestätige dein neues Passwort",
+ "message-new-password-missmatch": "Gebe das gleiche Passwort nochmals ein",
+ "passwordSecurity": "Passwortsicherheit",
+ "passwordStrength0": "Sehr unsicheres Passwort",
+ "passwordStrength1": "Unsicheres Passwort",
+ "passwordStrength2": "Mittelmäßiges Passwort",
+ "passwordStrength3": "Sicheres Passwort",
+ "passwordStrength4": "Sehr sicheres Passwort"
}
},
"invites": {
@@ -65,8 +81,10 @@
},
"social-media": {
"name": "Soziale Medien",
+ "placeholder": "Füge eine Social-Media URL hinzu",
"submit": "Link hinzufügen",
- "success": "Profil aktualisiert"
+ "successAdd": "Social-Media hinzugefügt. Profil aktualisiert!",
+ "successDelete": "Social-Media gelöscht. Profil aktualisiert!"
}
},
"admin": {
@@ -222,4 +240,4 @@
"shoutButton": {
"shouted": "empfohlen"
}
-}
+}
\ No newline at end of file
diff --git a/webapp/locales/en.json b/webapp/locales/en.json
index 2ab796f4a..186b31d41 100644
--- a/webapp/locales/en.json
+++ b/webapp/locales/en.json
@@ -21,6 +21,7 @@
"following": "Following",
"shouted": "Shouted",
"commented": "Commented",
+ "userAnonym": "Anonymous",
"socialMedia": "Where else can I find"
},
"notifications": {
@@ -38,14 +39,29 @@
"data": {
"name": "Your data",
"labelName": "Your Name",
+ "namePlaceholder": "Femanon Funny",
"labelCity": "Your City or Region",
- "labelBio": "About You"
+ "labelBio": "About You",
+ "success": "Your data was successfully updated!"
},
"security": {
"name": "Security",
"change-password": {
"button": "Change password",
- "success": "Password successfully changed!"
+ "success": "Password successfully changed!",
+ "label-old-password": "Your old password",
+ "label-new-password": "Your new password",
+ "label-new-password-confirm": "Confirm new password",
+ "message-old-password-required": "Enter your old password",
+ "message-new-password-required": "Enter a new password",
+ "message-new-password-confirm-required": "Confirm your new password",
+ "message-new-password-missmatch": "Type the same password again",
+ "passwordSecurity": "Password security",
+ "passwordStrength0": "Very insecure password",
+ "passwordStrength1": "Insecure password",
+ "passwordStrength2": "Mediocre password",
+ "passwordStrength3": "Strong password",
+ "passwordStrength4": "Very strong password"
}
},
"invites": {
@@ -65,8 +81,10 @@
},
"social-media": {
"name": "Social media",
+ "placeholder": "Add social media url",
"submit": "Add link",
- "success": "Updated user profile"
+ "successAdd": "Added social media. Updated user profile!",
+ "successDelete": "Deleted social media. Updated user profile!"
}
},
"admin": {
@@ -117,6 +135,14 @@
"takeAction": {
"name": "Take action"
},
+ "delete": {
+ "submit": "Delete",
+ "cancel": "Cancel",
+ "success": "Post deleted successfully",
+ "title": "Delete Post",
+ "type": "Contribution",
+ "message": "Do you really want to delete the post \"{name}\"?"
+ },
"comment": {
"submit": "Comment",
"submitted": "Comment Submitted"
@@ -222,4 +248,4 @@
"shoutButton": {
"shouted": "shouted"
}
-}
+}
\ No newline at end of file
diff --git a/webapp/locales/es.json b/webapp/locales/es.json
index ba46f9ec1..5beab2eef 100644
--- a/webapp/locales/es.json
+++ b/webapp/locales/es.json
@@ -88,6 +88,14 @@
},
"takeAction": {
"name": "Tomar acción"
+ },
+ "delete": {
+ "submit": "Borrar",
+ "cancel": "Cancelar",
+ "success": "Mensaje borrado satisfactoriamente",
+ "title": "Borrar mensaje",
+ "type": "Mensaje",
+ "message": "¿Realmente quieres borrar el mensaje \"{name}\"?"
}
},
"quotes": {
diff --git a/webapp/locales/it.json b/webapp/locales/it.json
index 0225babad..25005a07a 100644
--- a/webapp/locales/it.json
+++ b/webapp/locales/it.json
@@ -15,13 +15,15 @@
"followers": "Seguenti",
"following": "Seguendo",
"shouted": "Gridato",
- "commented": "Commentato"
+ "commented": "Commentato",
+ "userAnonym": "Anonymous"
},
"settings": {
"name": "Impostazioni",
"data": {
"name": "I tuoi dati",
"labelName": "Nome",
+ "namePlaceholder": "Anonymous",
"labelCity": "La tua città o regione",
"labelBio": "Su di te"
},
diff --git a/webapp/locales/pl.json b/webapp/locales/pl.json
index 0f2147996..506a04f1b 100644
--- a/webapp/locales/pl.json
+++ b/webapp/locales/pl.json
@@ -15,13 +15,15 @@
"followers": "Obserwujący",
"following": "Obserwowani",
"shouted": "Krzyknij",
- "commented": "Skomentuj"
+ "commented": "Skomentuj",
+ "userAnonym": "Anonymous"
},
"settings": {
"name": "Ustawienia",
"data": {
"name": "Twoje dane",
"labelName": "Twoje dane",
+ "namePlaceholder": "Anonymous",
"labelCity": "Twoje miasto lub region",
"labelBio": "O Tobie"
},
diff --git a/webapp/locales/pt.json b/webapp/locales/pt.json
index 4151f49c7..0636ba6f9 100644
--- a/webapp/locales/pt.json
+++ b/webapp/locales/pt.json
@@ -15,13 +15,15 @@
"followers": "Seguidores",
"following": "Seguindo",
"shouted": "Aclamou",
- "commented": "Comentou"
+ "commented": "Comentou",
+ "userAnonym": "Anonymous"
},
"settings": {
"name": "Configurações",
"data": {
"name": "Seus dados",
"labelName": "Seu nome",
+ "namePlaceholder": "Anonymous",
"labelCity": "Sua cidade ou estado",
"labelBio": "Sobre você"
},
diff --git a/webapp/package.json b/webapp/package.json
index e70d2b038..ae169888d 100644
--- a/webapp/package.json
+++ b/webapp/package.json
@@ -1,9 +1,13 @@
{
"name": "hc-webapp-next",
"version": "1.0.0",
- "description": "Human Connection GraphQL UI Prototype",
- "author": "Grzegorz Leoniec",
- "private": true,
+ "description": "Human Connection Frontend",
+ "authors": [
+ "Grzegorz Leoniec (appinteractive)",
+ "ulfgebhardt"
+ ],
+ "author": "",
+ "private": false,
"scripts": {
"dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
"dev:styleguide": "cross-env STYLEGUIDE_DEV=true yarn dev",
@@ -18,23 +22,35 @@
"jest": {
"verbose": true,
"collectCoverage": true,
- "coverageReporters": ["text", "lcov"],
- "moduleFileExtensions": [
- "js",
- "json",
- "vue"
+ "collectCoverageFrom": [
+ "**/*.{js,vue}",
+ "!**/node_modules/**",
+ "!**/.nuxt/**",
+ "!**/?(*.)+(spec|test).js?(x)"
+ ],
+ "coverageReporters": [
+ "text",
+ "lcov"
],
"transform": {
".*\\.(vue)$": "vue-jest",
"^.+\\.js$": "/node_modules/babel-jest"
},
+ "moduleFileExtensions": [
+ "js",
+ "json",
+ "vue"
+ ],
"moduleNameMapper": {
"^@/(.*)$": "/src/$1",
"^~/(.*)$": "/$1"
- }
+ },
+ "testMatch": [
+ "**/?(*.)+(spec|test).js?(x)"
+ ]
},
"dependencies": {
- "@human-connection/styleguide": "0.5.15",
+ "@human-connection/styleguide": "0.5.17",
"@nuxtjs/apollo": "4.0.0-rc4",
"@nuxtjs/axios": "~5.4.1",
"@nuxtjs/dotenv": "~1.3.0",
@@ -53,16 +69,18 @@
"nuxt-env": "~0.1.0",
"stack-utils": "^1.0.2",
"string-hash": "^1.1.3",
- "tiptap": "^1.18.0",
- "tiptap-extensions": "^1.18.1",
+ "tiptap": "1.17.0",
+ "tiptap-extensions": "1.17.0",
"v-tooltip": "~2.0.2",
"vue-count-to": "~1.0.13",
"vue-izitoast": "1.1.2",
"vue-sweetalert-icons": "~3.2.0",
- "vuex-i18n": "~1.11.0"
+ "vuex-i18n": "~1.11.0",
+ "zxcvbn": "^4.4.2"
},
"devDependencies": {
"@babel/core": "~7.4.4",
+ "@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "~7.4.4",
"@vue/cli-shared-utils": "~3.7.0",
"@vue/eslint-config-prettier": "~4.0.1",
@@ -82,8 +100,8 @@
"nodemon": "~1.19.0",
"prettier": "~1.14.3",
"sass-loader": "~7.1.0",
- "tippy.js": "^4.3.0",
+ "tippy.js": "^4.3.1",
"vue-jest": "~3.0.4",
"vue-svg-loader": "~0.12.0"
}
-}
+}
\ No newline at end of file
diff --git a/webapp/pages/login.vue b/webapp/pages/login.vue
index 92269143b..46c6e2d79 100644
--- a/webapp/pages/login.vue
+++ b/webapp/pages/login.vue
@@ -32,8 +32,8 @@
>
diff --git a/webapp/pages/logout.vue b/webapp/pages/logout.vue
index 008908360..1dc088c61 100644
--- a/webapp/pages/logout.vue
+++ b/webapp/pages/logout.vue
@@ -11,11 +11,11 @@
margin-bottom="xxx-small"
centered
>
-
+ />
+
+
diff --git a/webapp/pages/settings/security.vue b/webapp/pages/settings/security.vue
index 376f104e5..ac95ff26e 100644
--- a/webapp/pages/settings/security.vue
+++ b/webapp/pages/settings/security.vue
@@ -6,7 +6,7 @@