- mehr laden
+ {{ $t('actions.loadMore') }}
diff --git a/components/PostCard.vue b/components/PostCard.vue
index 450e69959..6d6f56256 100644
--- a/components/PostCard.vue
+++ b/components/PostCard.vue
@@ -41,11 +41,13 @@
- {{ post.shoutedCount }}
+
+ {{ post.shoutedCount }}
- {{ post.commentsCount }}
+
+ {{ post.commentsCount }}
diff --git a/cypress.json b/cypress.json
index af4800ea3..f41489007 100644
--- a/cypress.json
+++ b/cypress.json
@@ -1,4 +1,5 @@
{
"projectId": "qa7fe2",
- "ignoreTestFiles": "*.js"
+ "ignoreTestFiles": "*.js",
+ "baseUrl": "http://localhost:3000"
}
diff --git a/cypress/integration/Login.feature b/cypress/integration/01.Login.feature
similarity index 71%
rename from cypress/integration/Login.feature
rename to cypress/integration/01.Login.feature
index a7a47ddd5..72adc8553 100644
--- a/cypress/integration/Login.feature
+++ b/cypress/integration/01.Login.feature
@@ -5,8 +5,10 @@ Feature: Authentication
Background:
Given my account has the following details:
- | name | email | password |
- | Peter Lustig | admin@example.org | 1234 |
+ | name | email | password | type
+ | Peter Lustig | admin@example.org | 1234 | Admin
+ | Bob der Bausmeister | moderator@example.org | 1234 | Moderator
+ | Jenny Rostock" | user@example.org | 1234 | User
Scenario: Log in
When I visit the "/login" page
diff --git a/cypress/integration/Internationalization.feature b/cypress/integration/02.Internationalization.feature
similarity index 83%
rename from cypress/integration/Internationalization.feature
rename to cypress/integration/02.Internationalization.feature
index 375fc03aa..0a5f90ff0 100644
--- a/cypress/integration/Internationalization.feature
+++ b/cypress/integration/02.Internationalization.feature
@@ -13,12 +13,11 @@ Feature: Internationalization
Examples: Login Button
| language | buttonLabel |
- | English | Login |
- | Deutsch | Einloggen |
| Français | Connexion |
- | Nederlands | Inloggen |
+ | Deutsch | Einloggen |
+ | English | Login |
Scenario: Keep preferred language after refresh
- Given I previously switched the language to "Deutsch"
+ Given I previously switched the language to "Français"
And I refresh the page
- Then the whole user interface appears in "Deutsch"
+ Then the whole user interface appears in "Français"
diff --git a/cypress/integration/TagsAndCategories.feature b/cypress/integration/03.TagsAndCategories.feature
similarity index 100%
rename from cypress/integration/TagsAndCategories.feature
rename to cypress/integration/03.TagsAndCategories.feature
diff --git a/cypress/integration/04.AboutMeAndLocation.feature b/cypress/integration/04.AboutMeAndLocation.feature
new file mode 100644
index 000000000..83e7046f5
--- /dev/null
+++ b/cypress/integration/04.AboutMeAndLocation.feature
@@ -0,0 +1,45 @@
+Feature: About me and and location
+ As a user
+ I would like to add some about me text and a location
+ So others can get some info about me and my location
+
+ The location and about me are displayed on the user profile. Later it will be possible
+ to search for users by location.
+
+ Background:
+ Given I am logged in
+ And I am on the "settings" page
+
+ Scenario: Change username
+ When I save "Hansi" as my new name
+ Then I can see my new name "Hansi" when I click on my profile picture in the top right
+
+ Scenario: Keep changes after refresh
+ When I changed my username to "Hansi" previously
+ And I refresh the page
+ Then my new username is still there
+
+ Scenario Outline: I set my location to ""
+ When I save "" as my location
+ And my username is "Peter Lustig"
+ When people visit my profile page
+ Then they can see the location in the info box below my avatar
+
+ Examples: Location
+ | location | type |
+ | Paris | City |
+ | Saxony-Anhalt | Region |
+ | Germany | Country |
+
+ Scenario: Display a description on profile page
+ Given I have the following self-description:
+ """
+ Ich lebe fettlos, fleischlos, fischlos dahin, fühle mich aber ganz wohl dabei
+ """
+ And my username is "Peter Lustig"
+ When people visit my profile page
+ Then they can see the text in the info box below my avatar
+
+
+
+
diff --git a/cypress/integration/common/admin.js b/cypress/integration/common/admin.js
new file mode 100644
index 000000000..9162667b4
--- /dev/null
+++ b/cypress/integration/common/admin.js
@@ -0,0 +1,39 @@
+import { When, Then } from 'cypress-cucumber-preprocessor/steps'
+
+/* global cy */
+
+const lastColumnIsSortedInDescendingOrder = () => {
+ cy.get('tbody')
+ .find('tr td:last-child')
+ .then(lastColumn => {
+ cy.wrap(lastColumn)
+ const values = lastColumn
+ .map((i, td) => parseInt(td.textContent))
+ .toArray()
+ const orderedDescending = values.slice(0).sort((a, b) => b - a)
+ return cy.wrap(values).should('deep.eq', orderedDescending)
+ })
+}
+
+When('I navigate to the administration dashboard', () => {
+ cy.get('.avatar-menu').click()
+ cy.get('.avatar-menu-popover')
+ .find('a[href="/admin"]')
+ .click()
+})
+
+Then('I can see a list of categories ordered by post count:', table => {
+ // TODO: match the table in the feature with the html table
+ cy.get('thead')
+ .find('tr th')
+ .should('have.length', 3)
+ lastColumnIsSortedInDescendingOrder()
+})
+
+Then('I can see a list of tags ordered by user and post count:', table => {
+ // TODO: match the table in the feature with the html table
+ cy.get('thead')
+ .find('tr th')
+ .should('have.length', 4)
+ lastColumnIsSortedInDescendingOrder()
+})
diff --git a/cypress/integration/common/settings.js b/cypress/integration/common/settings.js
new file mode 100644
index 000000000..048f37b7a
--- /dev/null
+++ b/cypress/integration/common/settings.js
@@ -0,0 +1,76 @@
+import { When, Then } from 'cypress-cucumber-preprocessor/steps'
+
+/* global cy */
+
+let aboutMeText
+let myLocation
+let myName
+
+const matchNameInUserMenu = name => {
+ cy.get('.avatar-menu').click() // open
+ cy.get('.avatar-menu-popover').contains(name)
+ cy.get('.avatar-menu').click() // close again
+}
+
+const setUserName = name => {
+ cy.get('input[id=name]')
+ .clear()
+ .type(name)
+ cy.contains('Save')
+ .click()
+ .wait(200)
+ myName = name
+}
+
+When('I save {string} as my new name', name => {
+ setUserName(name)
+})
+
+When('I save {string} as my location', location => {
+ cy.get('input[id=city]').type(location)
+ cy.get('.ds-select-option')
+ .contains(location)
+ .click()
+ cy.contains('Save').click()
+ myLocation = location
+})
+
+When('I have the following self-description:', text => {
+ cy.get('textarea[id=bio]')
+ .clear()
+ .type(text)
+ cy.contains('Save').click()
+ aboutMeText = text
+})
+
+When('my username is {string}', name => {
+ if (myName !== name) {
+ setUserName(name)
+ }
+ matchNameInUserMenu(name)
+})
+
+When('people visit my profile page', url => {
+ cy.visitMyProfile()
+})
+
+When('they can see the text in the info box below my avatar', () => {
+ cy.contains(aboutMeText)
+})
+
+When('I changed my username to {string} previously', name => {
+ myName = name
+})
+
+Then('they can see the location in the info box below my avatar', () => {
+ matchNameInUserMenu(myName)
+})
+
+Then('my new username is still there', () => {
+ matchNameInUserMenu(myName)
+})
+
+Then(
+ 'I can see my new name {string} when I click on my profile picture in the top right',
+ name => matchNameInUserMenu(name)
+)
diff --git a/cypress/integration/common/steps.js b/cypress/integration/common/steps.js
index 78266d96e..ee9a364f7 100644
--- a/cypress/integration/common/steps.js
+++ b/cypress/integration/common/steps.js
@@ -1,63 +1,20 @@
import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps'
+import { getLangByName } from '../../support/helpers'
import find from 'lodash/find'
-/* global cy */
+/* global cy */
-const baseUrl = 'http://localhost:3000'
const username = 'Peter Lustig'
-const locales = require('../../../locales')
-
-const getLangByName = function(name) {
- return find(locales, { name })
-}
-
-const openPage = function(page) {
+const openPage = page => {
if (page === 'landing') {
page = ''
}
- cy.visit(`${baseUrl}/${page}`)
-}
-
-const switchLanguage = function(name) {
- cy.get('.login-locale-switch a').click()
- cy.contains('.locale-menu-popover a', name).click()
-}
-
-const login = (email, password) => {
- cy.visit(`${baseUrl}/login`)
- cy.get('input[name=email]')
- .trigger('focus')
- .type(email)
- cy.get('input[name=password]')
- .trigger('focus')
- .type(password)
- cy.get('button[name=submit]')
- .as('submitButton')
- .click()
- cy.location('pathname').should('eq', '/') // we're in!
-}
-
-const logout = () => {
- cy.visit(`${baseUrl}/logout`)
- cy.location('pathname').should('contain', '/login') // we're out
-}
-
-const lastColumnIsSortedInDescendingOrder = () => {
- cy.get('tbody')
- .find('tr td:last-child')
- .then(last_column => {
- cy.wrap(last_column)
- const values = last_column
- .map((i, td) => parseInt(td.textContent))
- .toArray()
- const ordered_descending = values.slice(0).sort((a, b) => b - a)
- return cy.wrap(values).should('deep.eq', ordered_descending)
- })
+ cy.visit(`/${page}`)
}
Given('I am logged in', () => {
- login('admin@example.org', 1234)
+ cy.login('admin@example.org', 1234)
})
Given('we have a selection of tags and categories as well as posts', () => {
@@ -72,7 +29,7 @@ Given('my user account has the role {string}', role => {
// TODO: use db factories instead of seed data
})
-When('I log out', logout)
+When('I log out', cy.logout)
When('I visit the {string} page', page => {
openPage(page)
@@ -82,7 +39,7 @@ Given('I am on the {string} page', page => {
})
When('I fill in my email and password combination and click submit', () => {
- login('admin@example.org', 1234)
+ cy.login('admin@example.org', 1234)
})
When('I refresh the page', () => {
@@ -92,8 +49,7 @@ When('I refresh the page', () => {
When('I log out through the menu in the top right corner', () => {
cy.get('.avatar-menu').click()
cy.get('.avatar-menu-popover')
- .find('a')
- .contains('Logout')
+ .find('a[href="/logout"]')
.click()
})
@@ -108,7 +64,6 @@ Then('I can see my name {string} in the dropdown menu', () => {
Then('I see the login screen again', () => {
cy.location('pathname').should('contain', '/login')
- cy.contains('If you already have a human-connection account, login here.')
})
Then('I am still logged in', () => {
@@ -117,10 +72,10 @@ Then('I am still logged in', () => {
})
When('I select {string} in the language menu', name => {
- switchLanguage(name)
+ cy.switchLanguage(name, true)
})
Given('I previously switched the language to {string}', name => {
- switchLanguage(name)
+ cy.switchLanguage(name, true)
})
Then('the whole user interface appears in {string}', name => {
const lang = getLangByName(name)
@@ -131,29 +86,10 @@ Then('I see a button with the label {string}', label => {
cy.contains('button', label)
})
-When('I navigate to the administration dashboard', () => {
- cy.get('.avatar-menu').click()
- cy.get('.avatar-menu-popover')
- .contains('Admin')
- .click()
-})
-
When(`I click on {string}`, linkOrButton => {
cy.contains(linkOrButton).click()
})
-Then('I can see a list of categories ordered by post count:', table => {
- // TODO: match the table in the feature with the html table
- cy.get('thead')
- .find('tr th')
- .should('have.length', 3)
- lastColumnIsSortedInDescendingOrder()
-})
-
-Then('I can see a list of tags ordered by user and post count:', table => {
- // TODO: match the table in the feature with the html table
- cy.get('thead')
- .find('tr th')
- .should('have.length', 4)
- lastColumnIsSortedInDescendingOrder()
+When('I press {string}', label => {
+ cy.contains(label).click()
})
diff --git a/cypress/support/commands.js b/cypress/support/commands.js
index c1f5a772e..77c75c7d5 100644
--- a/cypress/support/commands.js
+++ b/cypress/support/commands.js
@@ -10,16 +10,64 @@
//
//
// -- This is a parent command --
-// Cypress.Commands.add("login", (email, password) => { ... })
+// Cypress.Commands.add('login', (email, password) => { ... })
+
+/* globals Cypress cy */
+
+import { getLangByName } from './helpers'
+
+const switchLang = name => {
+ cy.get('.locale-menu').click()
+ cy.contains('.locale-menu-popover a', name).click()
+}
+
+Cypress.Commands.add('switchLanguage', (name, force) => {
+ const code = getLangByName(name).code
+ if (force) {
+ switchLang(name)
+ } else {
+ cy.get('html').then($html => {
+ if ($html && $html.attr('lang') !== code) {
+ switchLang(name)
+ }
+ })
+ }
+})
+
+Cypress.Commands.add('visitMyProfile', () => {
+ cy.get('.avatar-menu').click()
+ cy.get('.avatar-menu-popover')
+ .find('a[href^="/profile/"]')
+ .click()
+})
+
+Cypress.Commands.add('login', (email, password) => {
+ cy.visit(`/login`)
+ cy.get('input[name=email]')
+ .trigger('focus')
+ .type(email)
+ cy.get('input[name=password]')
+ .trigger('focus')
+ .type(password)
+ cy.get('button[name=submit]')
+ .as('submitButton')
+ .click()
+ cy.location('pathname').should('eq', '/') // we're in!
+})
+Cypress.Commands.add('logout', (email, password) => {
+ cy.visit(`/logout`)
+ cy.location('pathname').should('contain', '/login') // we're out
+})
+
//
//
// -- This is a child command --
-// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
+// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
-// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
+// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
-// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
+// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
diff --git a/cypress/support/config.js b/cypress/support/config.js
new file mode 100644
index 000000000..af96ad615
--- /dev/null
+++ b/cypress/support/config.js
@@ -0,0 +1,16 @@
+export default {
+ users: {
+ admin: {
+ email: 'admin@example.org',
+ password: 1234
+ },
+ moderator: {
+ email: 'moderator@example.org',
+ password: 1234
+ },
+ user: {
+ email: 'user@example.org',
+ password: 1234
+ }
+ }
+}
diff --git a/cypress/support/helpers.js b/cypress/support/helpers.js
new file mode 100644
index 000000000..661682139
--- /dev/null
+++ b/cypress/support/helpers.js
@@ -0,0 +1,11 @@
+
+import find from 'lodash/find'
+
+const helpers = {
+ locales: require('../../locales'),
+ getLangByName: name => {
+ return find(helpers.locales, { name })
+ }
+}
+
+export default helpers
diff --git a/docker-compose.yml b/docker-compose.yml
index c8bba8595..5a4c2ab5d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -14,6 +14,8 @@ services:
environment:
- HOST=0.0.0.0
- BACKEND_URL=http://backend:4000
+ - JWT_SECRET="b/&&7b78BF&fv/Vd"
+ - MAPBOX_TOKEN="pk.eyJ1IjoiaHVtYW4tY29ubmVjdGlvbiIsImEiOiJjajl0cnBubGoweTVlM3VwZ2lzNTNud3ZtIn0.bZ8KK9l70omjXbEkkbHGsQ"
networks:
hc-network:
diff --git a/graphql/UserProfileQuery.js b/graphql/UserProfileQuery.js
index 6374fd228..4e0245b52 100644
--- a/graphql/UserProfileQuery.js
+++ b/graphql/UserProfileQuery.js
@@ -1,72 +1,89 @@
import gql from 'graphql-tag'
-export default gql(`
- query User($slug: String!, $first: Int, $offset: Int) {
- User(slug: $slug) {
- id
- name
- avatar
- createdAt
- badges {
- id
- key
- icon
- }
- badgesCount
- shoutedCount
- commentsCount
- followingCount
- following(first: 7) {
+export default app => {
+ const lang = app.$i18n.locale().toUpperCase()
+ return gql(`
+ query User($slug: String!, $first: Int, $offset: Int) {
+ User(slug: $slug) {
id
name
- slug
avatar
- followedByCount
- contributionsCount
- commentsCount
+ about
+ locationName
+ location {
+ name: name${lang}
+ }
+ createdAt
badges {
id
key
icon
}
- }
- followedByCount
- followedBy(first: 7) {
- id
- name
- slug
- avatar
- followedByCount
- contributionsCount
- commentsCount
- badges {
- id
- key
- icon
- }
- }
- contributionsCount
- contributions(first: $first, offset: $offset, orderBy: createdAt_desc) {
- id
- slug
- title
- contentExcerpt
+ badgesCount
shoutedCount
commentsCount
- deleted
- image
- createdAt
- categories {
+ followingCount
+ following(first: 7) {
id
name
- icon
- }
- author {
- id
+ slug
avatar
+ followedByCount
+ contributionsCount
+ commentsCount
+ badges {
+ id
+ key
+ icon
+ }
+ location {
+ name: name${lang}
+ }
+ }
+ followedByCount
+ followedBy(first: 7) {
+ id
name
+ slug
+ avatar
+ followedByCount
+ contributionsCount
+ commentsCount
+ badges {
+ id
+ key
+ icon
+ }
+ location {
+ name: name${lang}
+ }
+ }
+ contributionsCount
+ contributions(first: $first, offset: $offset, orderBy: createdAt_desc) {
+ id
+ slug
+ title
+ contentExcerpt
+ shoutedCount
+ commentsCount
+ deleted
+ image
+ createdAt
+ categories {
+ id
+ name
+ icon
+ }
+ author {
+ id
+ avatar
+ name
+ location {
+ name: name${lang}
+ }
+ }
}
}
}
- }
-`)
+ `)
+}
diff --git a/layouts/default.vue b/layouts/default.vue
index 5080ac93b..a44da3422 100644
--- a/layouts/default.vue
+++ b/layouts/default.vue
@@ -47,6 +47,15 @@
>