@@ -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..f4ea82e37 100644
--- a/webapp/locales/de.json
+++ b/webapp/locales/de.json
@@ -21,6 +21,7 @@
"following": "Folgt",
"shouted": "Empfohlen",
"commented": "Kommentiert",
+ "userAnonym": "Anonymus",
"socialMedia": "Wo sonst finde ich"
},
"notifications": {
@@ -38,8 +39,10 @@
"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",
@@ -65,8 +68,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 +227,4 @@
"shoutButton": {
"shouted": "empfohlen"
}
-}
+}
\ No newline at end of file
diff --git a/webapp/locales/en.json b/webapp/locales/en.json
index 2ab796f4a..0dc953666 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,8 +39,10 @@
"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",
@@ -65,8 +68,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": {
@@ -222,4 +227,4 @@
"shoutButton": {
"shouted": "shouted"
}
-}
+}
\ No newline at end of file
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..d96385c53 100644
--- a/webapp/package.json
+++ b/webapp/package.json
@@ -18,20 +18,32 @@
"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",
@@ -63,6 +75,7 @@
},
"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",
@@ -86,4 +99,4 @@
"vue-jest": "~3.0.4",
"vue-svg-loader": "~0.12.0"
}
-}
+}
\ No newline at end of file
diff --git a/webapp/pages/profile/_id/_slug.vue b/webapp/pages/profile/_id/_slug.vue
index d577b79c8..ecb0baa9d 100644
--- a/webapp/pages/profile/_id/_slug.vue
+++ b/webapp/pages/profile/_id/_slug.vue
@@ -16,7 +16,7 @@
>
@@ -35,7 +35,7 @@
align="center"
no-margin
>
- {{ user.name }}
+ {{ userName }}
- Wem folgt {{ user.name | truncate(15) }}?
+ Wem folgt {{ userName | truncate(15) }}?
@@ -154,7 +154,7 @@
- {{ user.name }} folgt niemandem
+ {{ userName }} folgt niemandem
@@ -168,7 +168,7 @@
tag="h5"
color="soft"
>
- Wer folgt {{ user.name | truncate(15) }}?
+ Wer folgt {{ userName | truncate(15) }}?
@@ -199,18 +199,16 @@
- niemand folgt {{ user.name }}
+ niemand folgt {{ userName }}
-
-
+
-
+
{{ link.username }}
@@ -393,6 +389,10 @@ export default {
const username = url.split('/').pop()
return { url, username, favicon }
})
+ },
+ userName() {
+ const { name } = this.user || {}
+ return name || this.$t('profile.userAnonym')
}
},
watch: {
diff --git a/webapp/pages/settings/index.spec.js b/webapp/pages/settings/index.spec.js
new file mode 100644
index 000000000..8ee68172e
--- /dev/null
+++ b/webapp/pages/settings/index.spec.js
@@ -0,0 +1,73 @@
+import { mount, createLocalVue } from '@vue/test-utils'
+import index from './index.vue'
+import Vue from 'vue'
+import Vuex from 'vuex'
+import Styleguide from '@human-connection/styleguide'
+
+const localVue = createLocalVue()
+
+localVue.use(Vuex)
+localVue.use(Styleguide)
+
+describe('index.vue', () => {
+ let Wrapper
+ let store
+ let mocks
+ let getters
+
+ beforeEach(() => {
+ mocks = {
+ $t: jest.fn(),
+ $apollo: {
+ mutate: jest
+ .fn()
+ .mockRejectedValue({ message: 'Ouch!' })
+ .mockResolvedValueOnce({
+ data: {
+ UpdateUser: {
+ id: 'u1',
+ name: 'Peter',
+ locationName: 'Berlin',
+ about: 'Smth'
+ }
+ }
+ })
+ },
+ $toast: {
+ error: jest.fn(),
+ success: jest.fn()
+ }
+ }
+ getters = {
+ 'auth/user': () => {
+ return {}
+ }
+ }
+ })
+
+ describe('mount', () => {
+ const Wrapper = () => {
+ store = new Vuex.Store({
+ getters
+ })
+ return mount(index, { store, mocks, localVue })
+ }
+
+ it('renders', () => {
+ expect(Wrapper().contains('div')).toBe(true)
+ })
+
+ describe('given a new username and hitting submit', () => {
+ it('calls updateUser mutation', () => {
+ const wrapper = Wrapper()
+ const input = wrapper.find('#name')
+ const submitForm = wrapper.find('.ds-form')
+
+ input.setValue('Peter')
+ submitForm.trigger('submit')
+
+ expect(mocks.$apollo.mutate).toHaveBeenCalled()
+ })
+ })
+ })
+})
diff --git a/webapp/pages/settings/index.vue b/webapp/pages/settings/index.vue
index 5ff7c171e..a3b2298c3 100644
--- a/webapp/pages/settings/index.vue
+++ b/webapp/pages/settings/index.vue
@@ -9,7 +9,7 @@
model="name"
icon="user"
:label="$t('settings.data.labelName')"
- :placeholder="$t('settings.data.labelName')"
+ :placeholder="$t('settings.data.namePlaceholder')"
/>
@@ -36,7 +36,7 @@
style="float: right;"
icon="check"
type="submit"
- :loading="sending"
+ :loading="loadingData"
primary
>
{{ $t('actions.save') }}
@@ -88,8 +88,8 @@ export default {
return {
axiosSource: null,
cities: [],
- sending: false,
- loading: false,
+ loadingData: false,
+ loadingGeo: false,
formData: {}
}
},
@@ -111,13 +111,13 @@ export default {
...mapMutations({
setCurrentUser: 'auth/SET_USER'
}),
- submit() {
- this.sending = true
+ async submit() {
+ this.loadingData = true
const { name, about } = this.formData
let { locationName } = this.formData
locationName = locationName && (locationName['label'] || locationName)
- this.$apollo
- .mutate({
+ try {
+ const { data } = await this.$apollo.mutate({
mutation,
variables: {
id: this.currentUser.id,
@@ -135,15 +135,12 @@ export default {
})
}
})
- .then(data => {
- this.$toast.success('Updated user')
- })
- .catch(err => {
- this.$toast.error(err.message)
- })
- .finally(() => {
- this.sending = false
- })
+ this.$toast.success(this.$t('settings.data.success'))
+ } catch (err) {
+ this.$toast.error(err.message)
+ } finally {
+ this.loadingData = false
+ }
},
handleCityInput(value) {
clearTimeout(timeout)
@@ -181,7 +178,7 @@ export default {
return
}
- this.loading = true
+ this.loadingGeo = true
this.axiosSource = CancelToken.source()
const place = encodeURIComponent(value)
@@ -198,7 +195,7 @@ export default {
this.cities = this.processCityResults(res)
})
.finally(() => {
- this.loading = false
+ this.loadingGeo = false
})
}
}
diff --git a/webapp/pages/settings/my-social-media.spec.js b/webapp/pages/settings/my-social-media.spec.js
index 4f48a2835..559ba87d2 100644
--- a/webapp/pages/settings/my-social-media.spec.js
+++ b/webapp/pages/settings/my-social-media.spec.js
@@ -71,6 +71,40 @@ describe('my-social-media.vue', () => {
const socialMediaLink = wrapper.find('a').attributes().href
expect(socialMediaLink).toBe(socialMediaUrl)
})
+
+ beforeEach(() => {
+ mocks = {
+ $t: jest.fn(),
+ $apollo: {
+ mutate: jest
+ .fn()
+ .mockRejectedValue({ message: 'Ouch!' })
+ .mockResolvedValueOnce({
+ data: { DeleteSocialMeda: { id: 's1', url: socialMediaUrl } }
+ })
+ },
+ $toast: {
+ error: jest.fn(),
+ success: jest.fn()
+ }
+ }
+ getters = {
+ 'auth/user': () => {
+ return {
+ socialMedia: [{ id: 's1', url: socialMediaUrl }]
+ }
+ }
+ }
+ })
+
+ it('displays a trash sympol after a social media and allows the user to delete it', () => {
+ wrapper = Wrapper()
+ const deleteSelector = wrapper.find({ name: 'delete' })
+ expect(deleteSelector).toEqual({ selector: 'Component' })
+ const icon = wrapper.find({ name: 'trash' })
+ icon.trigger('click')
+ expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
+ })
})
describe('currentUser does not have a social media account linked', () => {
diff --git a/webapp/pages/settings/my-social-media.vue b/webapp/pages/settings/my-social-media.vue
index c031f54a4..462e9af96 100644
--- a/webapp/pages/settings/my-social-media.vue
+++ b/webapp/pages/settings/my-social-media.vue
@@ -8,9 +8,12 @@
-
+
{{ link.url }}
+ |
+
+
+
+
-
-
-
-
- {{ $t('settings.social-media.submit') }}
-
+
+
+
+
+ {{ $t('settings.social-media.submit') }}
+
+
+
@@ -59,13 +75,13 @@ export default {
socialMediaLinks() {
const { socialMedia = [] } = this.currentUser
return socialMedia.map(socialMedia => {
- const { url } = socialMedia
+ const { id, url } = socialMedia
const matches = url.match(
/^(?:https?:\/\/)?(?:[^@\n])?(?:www\.)?([^:\/\n?]+)/g
)
const [domain] = matches || []
const favicon = domain ? `${domain}/favicon.ico` : null
- return { url, favicon }
+ return { id, url, favicon }
})
}
},
@@ -79,6 +95,7 @@ export default {
mutation: gql`
mutation($url: String!) {
CreateSocialMedia(url: $url) {
+ id
url
}
}
@@ -97,11 +114,51 @@ export default {
})
}
})
- .then(
- this.$toast.success(this.$t('settings.social-media.success')),
- (this.value = '')
- )
+ .then(() => {
+ this.$toast.success(this.$t('settings.social-media.successAdd')),
+ (this.value = '')
+ })
+ .catch(error => {
+ this.$toast.error(error.message)
+ })
+ },
+ handleDeleteSocialMedia(link) {
+ this.$apollo
+ .mutate({
+ mutation: gql`
+ mutation($id: ID!) {
+ DeleteSocialMedia(id: $id) {
+ id
+ url
+ }
+ }
+ `,
+ variables: {
+ id: link.id
+ },
+ update: (store, { data }) => {
+ const socialMedia = this.currentUser.socialMedia.filter(
+ element => element.id !== link.id
+ )
+ this.setCurrentUser({
+ ...this.currentUser,
+ socialMedia
+ })
+ }
+ })
+ .then(() => {
+ this.$toast.success(this.$t('settings.social-media.successDelete'))
+ })
+ .catch(error => {
+ this.$toast.error(error.message)
+ })
}
}
}
+
+