From bc67ade3b6ed1fcbcae2619146262e1e1cb1d325 Mon Sep 17 00:00:00 2001
From: "dependabot-preview[bot]"
<27856297+dependabot-preview[bot]@users.noreply.github.com>
Date: Thu, 19 Mar 2020 04:19:12 +0000
Subject: [PATCH 001/108] build(deps): bump graphql-shield from 7.2.0 to 7.2.1
in /backend
Bumps [graphql-shield](https://github.com/maticzav/graphql-shield) from 7.2.0 to 7.2.1.
- [Release notes](https://github.com/maticzav/graphql-shield/releases)
- [Commits](https://github.com/maticzav/graphql-shield/compare/v7.2.0...v7.2.1)
Signed-off-by: dependabot-preview[bot]
---
backend/package.json | 2 +-
backend/yarn.lock | 18 +++++++++---------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/backend/package.json b/backend/package.json
index 77417453f..b2fee47b9 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -61,7 +61,7 @@
"graphql-middleware": "~4.0.2",
"graphql-middleware-sentry": "^3.2.1",
"graphql-redis-subscriptions": "^2.2.1",
- "graphql-shield": "~7.2.0",
+ "graphql-shield": "~7.2.1",
"graphql-tag": "~2.10.3",
"helmet": "~3.21.3",
"ioredis": "^4.16.0",
diff --git a/backend/yarn.lock b/backend/yarn.lock
index a514a60b4..8db891303 100644
--- a/backend/yarn.lock
+++ b/backend/yarn.lock
@@ -1587,10 +1587,10 @@
dependencies:
"@types/yargs-parser" "*"
-"@types/yup@0.26.32":
- version "0.26.32"
- resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.26.32.tgz#bd356fb405f3d641eff963854edf7ad854a8e829"
- integrity sha512-55WFAq8lNYXdRzSP1cenMFFXtPRe7PWsqn5y9ibqKHOQZ/cSLErkcnB1LE89M7W2TSXVDFtx+T7eFePkGoB+xw==
+"@types/yup@0.26.33":
+ version "0.26.33"
+ resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.26.33.tgz#301faab47b952a4a5f9a06246942cc7cbd09cd95"
+ integrity sha512-QzgcNfDtRIph8CjfoWiu+MJiOUp25Yo7FthuOHLVbtCTyonjOo2YRsFzKo3csDWbTXlw5NedOFH0Nje7yipCrA==
"@types/zen-observable@^0.8.0":
version "0.8.0"
@@ -4498,12 +4498,12 @@ graphql-redis-subscriptions@^2.2.1:
optionalDependencies:
ioredis "^4.6.3"
-graphql-shield@~7.2.0:
- version "7.2.0"
- resolved "https://registry.yarnpkg.com/graphql-shield/-/graphql-shield-7.2.0.tgz#81b26794370608ad78dfe3833473789fb471fbd8"
- integrity sha512-eLdD+gUIKYu77XRcuHs5ewZhiBuRFeWFGxPnJa+g9AkxB7Yi5RSEjEJEx0Drg9GuNvDYpHeW7nPff4v35AT2aQ==
+graphql-shield@~7.2.1:
+ version "7.2.1"
+ resolved "https://registry.yarnpkg.com/graphql-shield/-/graphql-shield-7.2.1.tgz#baca0c31a19593ede41a4bb4d476f9edd1d0eb78"
+ integrity sha512-EEoVYvXuqAGXGH1i9Aot4MJIUlRABVycwKRGaBreabys7yTd+0zGwudKB9yZiW3SEMIjHkz3a0r/ILhYzq0uiw==
dependencies:
- "@types/yup" "0.26.32"
+ "@types/yup" "0.26.33"
object-hash "^2.0.3"
yup "^0.28.3"
From e236838523a7dc991f8e301b3580734c4e611933 Mon Sep 17 00:00:00 2001
From: Moriz Wahl
Date: Fri, 7 Feb 2020 09:36:00 +0100
Subject: [PATCH 002/108] migration added for index for fulltext tag search
---
.../20200207080200-fulltext_index_for_tags.js | 49 +++++++++++++++++++
1 file changed, 49 insertions(+)
create mode 100644 backend/src/db/migrations/20200207080200-fulltext_index_for_tags.js
diff --git a/backend/src/db/migrations/20200207080200-fulltext_index_for_tags.js b/backend/src/db/migrations/20200207080200-fulltext_index_for_tags.js
new file mode 100644
index 000000000..0a92c90c3
--- /dev/null
+++ b/backend/src/db/migrations/20200207080200-fulltext_index_for_tags.js
@@ -0,0 +1,49 @@
+import { getDriver } from '../../db/neo4j'
+
+export const description =
+ 'This migration adds a fulltext index for the tags in order to search for Hasthags.'
+
+export async function up(next) {
+ const driver = getDriver()
+ const session = driver.session()
+ const transaction = session.beginTransaction()
+
+ try {
+ await transaction.run(`
+ CALL db.index.fulltext.createNodeIndex("tag_fulltext_search",["Tag"],["id"])
+ `)
+ await transaction.commit()
+ next()
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.log(error)
+ await transaction.rollback()
+ // eslint-disable-next-line no-console
+ console.log('rolled back')
+ } finally {
+ session.close()
+ }
+}
+
+export async function down(next) {
+ const driver = getDriver()
+ const session = driver.session()
+ const transaction = session.beginTransaction()
+
+ try {
+ // Implement your migration here.
+ await transaction.run(`
+ CALL db.index.fulltext.drop("tag_fulltext_search")
+ `)
+ await transaction.commit()
+ next()
+ } catch (error) {
+ // eslint-disable-next-line no-console
+ console.log(error)
+ await transaction.rollback()
+ // eslint-disable-next-line no-console
+ console.log('rolled back')
+ } finally {
+ session.close()
+ }
+}
From 16ad565ec8c3ff83d6b363861ada7ea0a29d3ce9 Mon Sep 17 00:00:00 2001
From: Moriz Wahl
Date: Tue, 11 Feb 2020 09:27:28 +0100
Subject: [PATCH 003/108] partially working, index page does not update when
route is changed
---
.../generic/SearchTag/SearchTag.vue | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
create mode 100644 webapp/components/generic/SearchTag/SearchTag.vue
diff --git a/webapp/components/generic/SearchTag/SearchTag.vue b/webapp/components/generic/SearchTag/SearchTag.vue
new file mode 100644
index 000000000..d8cfc0b31
--- /dev/null
+++ b/webapp/components/generic/SearchTag/SearchTag.vue
@@ -0,0 +1,23 @@
+
+
+
+ #{{ option.id }}
+
+
+
+
+
From 014be6e7f885a84668739a7697a53de5797fd61c Mon Sep 17 00:00:00 2001
From: Moriz Wahl
Date: Tue, 11 Feb 2020 09:27:41 +0100
Subject: [PATCH 004/108] partially working, index page does not update when
route is changed
---
backend/src/schema/resolvers/searches.js | 27 +++++++++++++--
backend/src/schema/types/type/Search.gql | 2 +-
webapp/components/Hashtag/Hashtag.vue | 2 +-
.../generic/SearchTag/SearchTag.vue | 24 ++++++-------
.../SearchableInput/SearchableInput.vue | 34 ++++++++++++++++---
webapp/graphql/Search.js | 3 ++
webapp/locales/de.json | 29 ++++++++++++++++
webapp/locales/en.json | 10 ++++++
8 files changed, 110 insertions(+), 21 deletions(-)
diff --git a/backend/src/schema/resolvers/searches.js b/backend/src/schema/resolvers/searches.js
index 5c1e43952..d4a2bf02a 100644
--- a/backend/src/schema/resolvers/searches.js
+++ b/backend/src/schema/resolvers/searches.js
@@ -43,6 +43,16 @@ export default {
`
const myQuery = queryString(query)
+ const tagCypher = `
+ CALL db.index.fulltext.queryNodes('tag_fulltext_search', $query)
+ YIELD node as resource, score
+ MATCH (resource)
+ WHERE score >= 0.5
+ AND NOT (resource.deleted = true OR resource.disabled = true)
+ RETURN resource {.*, __typename: labels(resource)[0]}
+ LIMIT $limit
+ `
+
const session = context.driver.session()
const searchResultPromise = session.readTransaction(async transaction => {
const postTransactionResponse = transaction.run(postCypher, {
@@ -55,14 +65,25 @@ export default {
limit,
thisUserId,
})
- return Promise.all([postTransactionResponse, userTransactionResponse])
+ const tagTransactionResponse = transaction.run(tagCypher, {
+ query: myQuery,
+ limit,
+ })
+ return Promise.all([
+ postTransactionResponse,
+ userTransactionResponse,
+ tagTransactionResponse,
+ ])
})
try {
- const [postResults, userResults] = await searchResultPromise
+ const [postResults, userResults, tagResults] = await searchResultPromise
log(postResults)
log(userResults)
- return [...postResults.records, ...userResults.records].map(r => r.get('resource'))
+ log(tagResults)
+ return [...postResults.records, ...userResults.records, ...tagResults.records].map(r =>
+ r.get('resource'),
+ )
} finally {
session.close()
}
diff --git a/backend/src/schema/types/type/Search.gql b/backend/src/schema/types/type/Search.gql
index 2c22fa61f..1ce38001d 100644
--- a/backend/src/schema/types/type/Search.gql
+++ b/backend/src/schema/types/type/Search.gql
@@ -1,4 +1,4 @@
-union SearchResult = Post | User
+union SearchResult = Post | User | Tag
type Query {
findResources(query: String!, limit: Int = 5): [SearchResult]!
diff --git a/webapp/components/Hashtag/Hashtag.vue b/webapp/components/Hashtag/Hashtag.vue
index 35762c81c..44e5319f0 100644
--- a/webapp/components/Hashtag/Hashtag.vue
+++ b/webapp/components/Hashtag/Hashtag.vue
@@ -1,5 +1,5 @@
-
+
#{{ id }}
diff --git a/webapp/components/generic/SearchTag/SearchTag.vue b/webapp/components/generic/SearchTag/SearchTag.vue
index d8cfc0b31..a94431eea 100644
--- a/webapp/components/generic/SearchTag/SearchTag.vue
+++ b/webapp/components/generic/SearchTag/SearchTag.vue
@@ -6,18 +6,18 @@
diff --git a/webapp/components/generic/SearchableInput/SearchableInput.vue b/webapp/components/generic/SearchableInput/SearchableInput.vue
index 3260ff082..654deaad4 100644
--- a/webapp/components/generic/SearchableInput/SearchableInput.vue
+++ b/webapp/components/generic/SearchableInput/SearchableInput.vue
@@ -35,6 +35,12 @@
>
+
+
+
@@ -45,6 +51,7 @@
import { isEmpty } from 'lodash'
import SearchHeading from '~/components/generic/SearchHeading/SearchHeading.vue'
import SearchPost from '~/components/generic/SearchPost/SearchPost.vue'
+import HcHashtag from '~/components/Hashtag/Hashtag.vue'
import UserTeaser from '~/components/UserTeaser/UserTeaser.vue'
export default {
@@ -52,6 +59,7 @@ export default {
components: {
SearchHeading,
SearchPost,
+ HcHashtag,
UserTeaser,
},
props: {
@@ -77,6 +85,16 @@ export default {
return !isEmpty(this.previousSearchTerm)
},
},
+ watch: {
+ $route(to, from) {
+ console.log('to', to)
+ console.log('from', from)
+ // console.log(this.finalFilters)
+ if (to.query.hashtag) {
+ this.hashtag = to.query.hashtag
+ }
+ },
+ },
methods: {
isFirstOfType(option) {
return (
@@ -138,12 +156,20 @@ export default {
isPost(item) {
return item.__typename === 'Post'
},
+ isTag(item) {
+ return item.__typename === 'Tag'
+ },
goToResource(item) {
this.$nextTick(() => {
- this.$router.push({
- name: this.isPost(item) ? 'post-id-slug' : 'profile-id-slug',
- params: { id: item.id, slug: item.slug },
- })
+ if (!this.isTag(item)) {
+ this.$router.push({
+ name: this.isPost(item) ? 'post-id-slug' : 'profile-id-slug',
+ params: { id: item.id, slug: item.slug },
+ })
+ } else {
+ console.log('HIT¡')
+ this.$router.push('?hashtag=' + item.id)
+ }
})
},
},
diff --git a/webapp/graphql/Search.js b/webapp/graphql/Search.js
index 9b142b429..ab34b58b6 100644
--- a/webapp/graphql/Search.js
+++ b/webapp/graphql/Search.js
@@ -19,6 +19,9 @@ export const findResourcesQuery = gql`
... on User {
...user
}
+ ... on Tag {
+ id
+ }
}
}
`
diff --git a/webapp/locales/de.json b/webapp/locales/de.json
index 524ee58fa..8f38c2352 100644
--- a/webapp/locales/de.json
+++ b/webapp/locales/de.json
@@ -558,6 +558,35 @@
"message": "Bist Du sicher, dass Du den Kommentar von „{name}“ melden möchtest?",
"title": "Kommentar melden",
"type": "Kommentar"
+ "content": {
+ "unavailable-placeholder": "… dieser Kommentar ist nicht mehr verfügbar"
+ },
+ "menu": {
+ "edit": "Kommentar bearbeiten",
+ "delete": "Kommentar löschen"
+ },
+ "show": {
+ "more": "mehr anzeigen",
+ "less": "weniger anzeigen"
+ },
+ "edited": "bearbeitet"
+ },
+ "followButton": {
+ "follow": "Folgen",
+ "following": "Folge Ich"
+ },
+ "shoutButton": {
+ "shouted": "empfohlen"
+ },
+ "search": {
+ "placeholder": "Suchen",
+ "hint": "Wonach suchst Du?",
+ "failed": "Nichts gefunden",
+ "heading": {
+ "Post": "Beiträge",
+ "User": "Benutzer",
+ "Tag": "Hashtags"
+ }
},
"contribution": {
"error": "Du hast den Beitrag bereits gemeldet!",
diff --git a/webapp/locales/en.json b/webapp/locales/en.json
index e6b8def5a..642d0c228 100644
--- a/webapp/locales/en.json
+++ b/webapp/locales/en.json
@@ -549,6 +549,16 @@
"message": "Do you really want to release the user \"{name}\"?",
"title": "Release User",
"type": "User"
+ "empty": "Sorry, you don't have any notifications at the moment."
+ },
+ "search": {
+ "placeholder": "Search",
+ "hint": "What are you searching for?",
+ "failed": "Nothing found",
+ "heading": {
+ "Post": "Posts",
+ "User": "Users",
+ "Tag": "Hashtags"
}
},
"report": {
From 07fbe92fa81ab3828904545d9d58cd67e02238d3 Mon Sep 17 00:00:00 2001
From: Moriz Wahl
Date: Thu, 19 Mar 2020 13:26:08 +0100
Subject: [PATCH 005/108] fixed locales after mistakes in rebase
---
webapp/locales/de.json | 30 +-----------------------------
webapp/locales/en.json | 11 +----------
2 files changed, 2 insertions(+), 39 deletions(-)
diff --git a/webapp/locales/de.json b/webapp/locales/de.json
index 8f38c2352..a2ab2246f 100644
--- a/webapp/locales/de.json
+++ b/webapp/locales/de.json
@@ -558,35 +558,6 @@
"message": "Bist Du sicher, dass Du den Kommentar von „{name}“ melden möchtest?",
"title": "Kommentar melden",
"type": "Kommentar"
- "content": {
- "unavailable-placeholder": "… dieser Kommentar ist nicht mehr verfügbar"
- },
- "menu": {
- "edit": "Kommentar bearbeiten",
- "delete": "Kommentar löschen"
- },
- "show": {
- "more": "mehr anzeigen",
- "less": "weniger anzeigen"
- },
- "edited": "bearbeitet"
- },
- "followButton": {
- "follow": "Folgen",
- "following": "Folge Ich"
- },
- "shoutButton": {
- "shouted": "empfohlen"
- },
- "search": {
- "placeholder": "Suchen",
- "hint": "Wonach suchst Du?",
- "failed": "Nichts gefunden",
- "heading": {
- "Post": "Beiträge",
- "User": "Benutzer",
- "Tag": "Hashtags"
- }
},
"contribution": {
"error": "Du hast den Beitrag bereits gemeldet!",
@@ -628,6 +599,7 @@
"failed": "Nichts gefunden",
"heading": {
"Post": "Beiträge",
+ "Tag": "Hashtags",
"User": "Benutzer"
},
"hint": "Wonach suchst Du?",
diff --git a/webapp/locales/en.json b/webapp/locales/en.json
index 642d0c228..eb19dfbe7 100644
--- a/webapp/locales/en.json
+++ b/webapp/locales/en.json
@@ -549,16 +549,6 @@
"message": "Do you really want to release the user \"{name}\"?",
"title": "Release User",
"type": "User"
- "empty": "Sorry, you don't have any notifications at the moment."
- },
- "search": {
- "placeholder": "Search",
- "hint": "What are you searching for?",
- "failed": "Nothing found",
- "heading": {
- "Post": "Posts",
- "User": "Users",
- "Tag": "Hashtags"
}
},
"report": {
@@ -609,6 +599,7 @@
"failed": "Nothing found",
"heading": {
"Post": "Posts",
+ "Tag": "Hashtags",
"User": "Users"
},
"hint": "What are you searching for?",
From 1c43d5fe6f44c7b11168af8bd765b8d785a6641a Mon Sep 17 00:00:00 2001
From: Moriz Wahl
Date: Thu, 19 Mar 2020 14:19:13 +0100
Subject: [PATCH 006/108] Search for Hashtags works due watching route in
pages/index.vue
---
backend/src/db/migrate/template.js | 1 +
.../20200207080200-fulltext_index_for_tags.js | 2 +
backend/src/schema/resolvers/searches.js | 6 +-
.../generic/SearchTag/SearchTag.vue | 23 --
.../SearchableInput/SearchableInput.vue | 11 -
webapp/pages/index.vue | 306 +++++++++---------
6 files changed, 162 insertions(+), 187 deletions(-)
delete mode 100644 webapp/components/generic/SearchTag/SearchTag.vue
diff --git a/backend/src/db/migrate/template.js b/backend/src/db/migrate/template.js
index 9adb0786d..72bfc9b1b 100644
--- a/backend/src/db/migrate/template.js
+++ b/backend/src/db/migrate/template.js
@@ -40,6 +40,7 @@ export async function down(next) {
await transaction.rollback()
// eslint-disable-next-line no-console
console.log('rolled back')
+ throw new Error(error)
} finally {
session.close()
}
diff --git a/backend/src/db/migrations/20200207080200-fulltext_index_for_tags.js b/backend/src/db/migrations/20200207080200-fulltext_index_for_tags.js
index 0a92c90c3..5064a8b17 100644
--- a/backend/src/db/migrations/20200207080200-fulltext_index_for_tags.js
+++ b/backend/src/db/migrations/20200207080200-fulltext_index_for_tags.js
@@ -20,6 +20,7 @@ export async function up(next) {
await transaction.rollback()
// eslint-disable-next-line no-console
console.log('rolled back')
+ throw new Error(error)
} finally {
session.close()
}
@@ -43,6 +44,7 @@ export async function down(next) {
await transaction.rollback()
// eslint-disable-next-line no-console
console.log('rolled back')
+ throw new Error(error)
} finally {
session.close()
}
diff --git a/backend/src/schema/resolvers/searches.js b/backend/src/schema/resolvers/searches.js
index d4a2bf02a..3471c783b 100644
--- a/backend/src/schema/resolvers/searches.js
+++ b/backend/src/schema/resolvers/searches.js
@@ -41,18 +41,18 @@ export default {
RETURN resource {.*, __typename: labels(resource)[0]}
LIMIT $limit
`
- const myQuery = queryString(query)
-
const tagCypher = `
CALL db.index.fulltext.queryNodes('tag_fulltext_search', $query)
YIELD node as resource, score
MATCH (resource)
- WHERE score >= 0.5
+ WHERE score >= 0.0
AND NOT (resource.deleted = true OR resource.disabled = true)
RETURN resource {.*, __typename: labels(resource)[0]}
LIMIT $limit
`
+ const myQuery = queryString(query)
+
const session = context.driver.session()
const searchResultPromise = session.readTransaction(async transaction => {
const postTransactionResponse = transaction.run(postCypher, {
diff --git a/webapp/components/generic/SearchTag/SearchTag.vue b/webapp/components/generic/SearchTag/SearchTag.vue
deleted file mode 100644
index a94431eea..000000000
--- a/webapp/components/generic/SearchTag/SearchTag.vue
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- #{{ option.id }}
-
-
-
-
-
diff --git a/webapp/components/generic/SearchableInput/SearchableInput.vue b/webapp/components/generic/SearchableInput/SearchableInput.vue
index 654deaad4..b0050b429 100644
--- a/webapp/components/generic/SearchableInput/SearchableInput.vue
+++ b/webapp/components/generic/SearchableInput/SearchableInput.vue
@@ -85,16 +85,6 @@ export default {
return !isEmpty(this.previousSearchTerm)
},
},
- watch: {
- $route(to, from) {
- console.log('to', to)
- console.log('from', from)
- // console.log(this.finalFilters)
- if (to.query.hashtag) {
- this.hashtag = to.query.hashtag
- }
- },
- },
methods: {
isFirstOfType(option) {
return (
@@ -167,7 +157,6 @@ export default {
params: { id: item.id, slug: item.slug },
})
} else {
- console.log('HIT¡')
this.$router.push('?hashtag=' + item.id)
}
})
diff --git a/webapp/pages/index.vue b/webapp/pages/index.vue
index 8aef52c1d..d73c993ec 100644
--- a/webapp/pages/index.vue
+++ b/webapp/pages/index.vue
@@ -64,158 +64,164 @@
diff --git a/webapp/components/FilterMenu/FilterMenu.spec.js b/webapp/components/FilterMenu/FilterMenu.spec.js
index 283db979e..ec94e8ea5 100644
--- a/webapp/components/FilterMenu/FilterMenu.spec.js
+++ b/webapp/components/FilterMenu/FilterMenu.spec.js
@@ -1,42 +1,166 @@
import { mount } from '@vue/test-utils'
+
+import Vuex from 'vuex'
import FilterMenu from './FilterMenu.vue'
+import locales from '~/locales'
+import orderBy from 'lodash/orderBy'
const localVue = global.localVue
+let mutations
+let getters
+
+const languages = orderBy(locales, 'name')
+
describe('FilterMenu.vue', () => {
- let wrapper
let mocks
let propsData
+ let menuToggle
+ let allCategoriesButton
+ let environmentAndNatureButton
+ let democracyAndPoliticsButton
+ let happyEmotionButton
+ let englishButton
+ let spanishButton
beforeEach(() => {
- mocks = { $t: () => {} }
+ mocks = {
+ $apollo: {
+ query: jest
+ .fn()
+ .mockResolvedValueOnce({
+ data: { Post: { title: 'Post with Category', category: [{ id: 'cat4' }] } },
+ })
+ .mockRejectedValue({ message: 'We were unable to filter' }),
+ },
+ $t: jest.fn(),
+ $i18n: {
+ locale: () => 'en',
+ },
+ $toast: {
+ error: jest.fn(),
+ },
+ }
+ propsData = {
+ categories: [
+ { id: 'cat4', name: 'Environment & Nature', icon: 'tree' },
+ { id: 'cat15', name: 'Consumption & Sustainability', icon: 'shopping-cart' },
+ { id: 'cat9', name: 'Democracy & Politics', icon: 'university' },
+ ],
+ }
})
- describe('given a hashtag', () => {
- beforeEach(() => {
- propsData = {
- hashtag: 'Frieden',
- }
+ describe('mount', () => {
+ mutations = {
+ 'posts/TOGGLE_FILTER_BY_FOLLOWED': jest.fn(),
+ 'posts/RESET_CATEGORIES': jest.fn(),
+ 'posts/TOGGLE_CATEGORY': jest.fn(),
+ 'posts/TOGGLE_EMOTION': jest.fn(),
+ 'posts/TOGGLE_LANGUAGE': jest.fn(),
+ 'posts/RESET_LANGUAGES': jest.fn(),
+ }
+ getters = {
+ 'posts/isActive': () => false,
+ 'auth/isModerator': () => false,
+ 'auth/user': () => {
+ return { id: 'u34' }
+ },
+ 'posts/filteredCategoryIds': jest.fn(() => []),
+ 'posts/filteredByUsersFollowed': jest.fn(),
+ 'posts/filteredByEmotions': jest.fn(() => []),
+ 'posts/filteredLanguageCodes': jest.fn(() => []),
+ }
+ const openFilterMenu = () => {
+ const store = new Vuex.Store({ mutations, getters })
+ const wrapper = mount(FilterMenu, { mocks, localVue, propsData, store })
+ menuToggle = wrapper.findAll('button').at(0)
+ menuToggle.trigger('click')
+ return wrapper
+ }
+
+ it('groups the categories by pair', () => {
+ const wrapper = openFilterMenu()
+ expect(wrapper.vm.chunk).toEqual([
+ [
+ { id: 'cat4', name: 'Environment & Nature', icon: 'tree' },
+ { id: 'cat15', name: 'Consumption & Sustainability', icon: 'shopping-cart' },
+ ],
+ [{ id: 'cat9', name: 'Democracy & Politics', icon: 'university' }],
+ ])
})
- describe('mount', () => {
- const Wrapper = () => {
- return mount(FilterMenu, { mocks, localVue, propsData })
- }
+ it('starts with all categories button active', () => {
+ const wrapper = openFilterMenu()
+ allCategoriesButton = wrapper.findAll('button').at(1)
+ expect(allCategoriesButton.attributes().class).toContain('--filled')
+ })
+
+ it('calls TOGGLE_CATEGORY when clicked', () => {
+ const wrapper = openFilterMenu()
+ environmentAndNatureButton = wrapper.findAll('button').at(2)
+ environmentAndNatureButton.trigger('click')
+ expect(mutations['posts/TOGGLE_CATEGORY']).toHaveBeenCalledWith({}, 'cat4')
+ })
+
+ it('calls TOGGLE_LANGUAGE when clicked', () => {
+ const wrapper = openFilterMenu()
+ englishButton = wrapper
+ .findAll('button.language-buttons')
+ .at(languages.findIndex(l => l.code === 'en'))
+ englishButton.trigger('click')
+ expect(mutations['posts/TOGGLE_LANGUAGE']).toHaveBeenCalledWith({}, 'en')
+ })
+
+ it('sets category button attribute `filled` when corresponding category is filtered', () => {
+ getters['posts/filteredCategoryIds'] = jest.fn(() => ['cat9'])
+ const wrapper = openFilterMenu()
+ democracyAndPoliticsButton = wrapper.findAll('button').at(4)
+ expect(democracyAndPoliticsButton.attributes().class).toContain('--filled')
+ })
+
+ it('sets language button attribute `filled` when corresponding language is filtered', () => {
+ getters['posts/filteredLanguageCodes'] = jest.fn(() => ['es'])
+ const wrapper = openFilterMenu()
+ spanishButton = wrapper
+ .findAll('button.language-buttons')
+ .at(languages.findIndex(l => l.code === 'es'))
+ expect(spanishButton.attributes().class).toContain('--filled')
+ })
+
+ it('sets "filter-by-followed" button attribute `filled`', () => {
+ getters['posts/filteredByUsersFollowed'] = jest.fn(() => true)
+ const wrapper = openFilterMenu()
+ expect(wrapper.find('.base-button[data-test="filter-by-followed"]').classes('--filled')).toBe(
+ true,
+ )
+ })
+
+ describe('click "filter-by-followed" button', () => {
+ let wrapper
beforeEach(() => {
- wrapper = Wrapper()
+ wrapper = openFilterMenu()
+ wrapper.find('.base-button[data-test="filter-by-followed"]').trigger('click')
})
- it('renders a card', () => {
- wrapper = Wrapper()
- expect(wrapper.is('.base-card')).toBe(true)
+ it('calls TOGGLE_FILTER_BY_FOLLOWED', () => {
+ expect(mutations['posts/TOGGLE_FILTER_BY_FOLLOWED']).toHaveBeenCalledWith({}, 'u34')
+ })
+ })
+
+ describe('click on an "emotions-buttons" button', () => {
+ it('calls TOGGLE_EMOTION when clicked', () => {
+ const wrapper = openFilterMenu()
+ happyEmotionButton = wrapper.findAll('.emotion-button .base-button').at(1)
+ happyEmotionButton.trigger('click')
+ expect(mutations['posts/TOGGLE_EMOTION']).toHaveBeenCalledWith({}, 'happy')
})
- describe('click clear search button', () => {
- it('emits clearSearch', () => {
- wrapper.find('.base-button').trigger('click')
- expect(wrapper.emitted().clearSearch).toHaveLength(1)
- })
+ it('sets the attribute `src` to colorized image', () => {
+ getters['posts/filteredByEmotions'] = jest.fn(() => ['happy'])
+ const wrapper = openFilterMenu()
+ happyEmotionButton = wrapper.findAll('.emotion-button .base-button').at(1)
+ const happyEmotionButtonImage = happyEmotionButton.find('img')
+ expect(happyEmotionButtonImage.attributes().src).toEqual('/img/svg/emoji/happy_color.svg')
})
})
})
diff --git a/webapp/components/FilterMenu/FilterMenu.vue b/webapp/components/FilterMenu/FilterMenu.vue
index afe6a3d7a..0cc21f04d 100644
--- a/webapp/components/FilterMenu/FilterMenu.vue
+++ b/webapp/components/FilterMenu/FilterMenu.vue
@@ -1,36 +1,46 @@
-
+ slot="default"
+ icon="filter"
+ :filled="filterActive"
+ :ghost="!filterActive"
+ slot-scope="{ toggleMenu }"
+ @click.prevent="toggleMenu()"
+ >
+
+
+
+
+
+
+
+
+
+
-
-
-
diff --git a/webapp/components/FilterPosts/GeneralFilterMenuItems.vue b/webapp/components/FilterMenu/GeneralFilter.vue
similarity index 83%
rename from webapp/components/FilterPosts/GeneralFilterMenuItems.vue
rename to webapp/components/FilterMenu/GeneralFilter.vue
index f1cf6adae..f13e6b778 100644
--- a/webapp/components/FilterPosts/GeneralFilterMenuItems.vue
+++ b/webapp/components/FilterMenu/GeneralFilter.vue
@@ -1,7 +1,7 @@
-