From d6f8b0dc773e527ebdef1381fb4a41ca87147006 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 31 Aug 2022 14:28:25 +0200 Subject: [PATCH 01/13] change category to topic in german and english locales --- webapp/locales/de.json | 18 +++++++++--------- webapp/locales/en.json | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/webapp/locales/de.json b/webapp/locales/de.json index dee8d086a..b17e47d08 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -11,7 +11,7 @@ "admin": { "categories": { "categoryName": "Name", - "name": "Kategorien", + "name": "Themen", "postCount": "Beiträge" }, "dashboard": { @@ -98,7 +98,7 @@ } }, "common": { - "category": "Kategorie ::: Kategorien", + "category": "Thema ::: Themen", "comment": "Kommentar ::: Kommentare", "letsTalk": "Miteinander reden", "loading": "wird geladen", @@ -113,7 +113,7 @@ "takeAction": "Aktiv werden", "user": "Benutzer ::: Benutzer", "validations": { - "categories": "es müssen eine bis drei Kategorien ausgewählt werden", + "categories": "es müssen eine bis drei Themen ausgewählt werden", "email": "muss eine gültige E-Mail-Adresse sein", "url": "muss eine gültige URL sein" }, @@ -214,7 +214,7 @@ "amount-shouts": "{amount} recommendations", "amount-views": "{amount} views", "categories": { - "infoSelectedNoOfMaxCategories": "{chosen} von {max} Kategorien ausgewählt" + "infoSelectedNoOfMaxCategories": "{chosen} von {max} Themen ausgewählt" }, "category": { "name": { @@ -348,7 +348,7 @@ }, "filter-menu": { "all": "Alle", - "categories": "Themenkategorien", + "categories": "Themen", "emotions": "Emotionen", "filter-by": "Filtern nach ...", "following": "Benutzern, denen ich folge", @@ -470,7 +470,7 @@ "noDecision": "Keine Entscheidung!", "numberOfUsers": "{count} Nutzern", "previousDecision": "Vorherige Entscheidung:", - "reasonCategory": "Kategorie", + "reasonCategory": "Thema", "reasonDescription": "Beschreibung", "reportedOn": "Datum", "status": "Aktueller Status", @@ -587,8 +587,8 @@ }, "reason": { "category": { - "invalid": "Bitte wähle eine gültige Kategorie aus", - "label": "Wähle eine Kategorie:", + "invalid": "Bitte wähle ein gültiges Thema aus", + "label": "Wähle ein Thema:", "options": { "advert_products_services_commercial": "Bewerben von Produkten und Dienstleistungen mit kommerzieller Absicht.", "criminal_behavior_violation_german_law": "Strafbares Verhalten bzw. Verstoß gegen deutsches Recht.", @@ -599,7 +599,7 @@ "other": "Andere …", "pornographic_content_links": "Das Senden oder Verlinken eindeutig pornografischen Materials." }, - "placeholder": "Kategorie …" + "placeholder": "Thema …" }, "description": { "label": "Bitte erkläre: Warum möchtest Du dies melden?", diff --git a/webapp/locales/en.json b/webapp/locales/en.json index d6172c257..8587d9da5 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -11,7 +11,7 @@ "admin": { "categories": { "categoryName": "Name", - "name": "Categories", + "name": "Topics", "postCount": "Posts" }, "dashboard": { @@ -98,7 +98,7 @@ } }, "common": { - "category": "Category ::: Categories", + "category": "Topic ::: Topics", "comment": "Comment ::: Comments", "letsTalk": "Let`s Talk", "loading": "loading", @@ -113,7 +113,7 @@ "takeAction": "Take Action", "user": "User ::: Users", "validations": { - "categories": "at least one and at most three categories must be selected", + "categories": "at least one and at most three topics must be selected", "email": "must be a valid e-mail address", "url": "must be a valid URL" }, @@ -214,7 +214,7 @@ "amount-shouts": "{amount} recommendations", "amount-views": "{amount} views", "categories": { - "infoSelectedNoOfMaxCategories": "{chosen} of {max} categories selected" + "infoSelectedNoOfMaxCategories": "{chosen} of {max} topics selected" }, "category": { "name": { @@ -348,7 +348,7 @@ }, "filter-menu": { "all": "All", - "categories": "Categories of Content", + "categories": "Topics", "emotions": "Emotions", "filter-by": "Filter by ...", "following": "Users I follow", @@ -470,7 +470,7 @@ "noDecision": "No decision!", "numberOfUsers": "{count} users", "previousDecision": "Previous decision:", - "reasonCategory": "Category", + "reasonCategory": "Topic", "reasonDescription": "Description", "reportedOn": "Date", "status": "Current status", @@ -587,8 +587,8 @@ }, "reason": { "category": { - "invalid": "Please select a valid category", - "label": "Select a category:", + "invalid": "Please select a valid topic", + "label": "Select a topic:", "options": { "advert_products_services_commercial": "Advertising products and services with commercial intent.", "criminal_behavior_violation_german_law": "Criminal behavior or violation of German law.", @@ -599,7 +599,7 @@ "other": "Other …", "pornographic_content_links": "Posting or linking of clearly pornographic material." }, - "placeholder": "Category …" + "placeholder": "Topic …" }, "description": { "label": "Please explain: Why you like to report this?", From 87aa47d68345bf851cdc3b3e00ca1e434196ce6f Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 31 Aug 2022 14:32:46 +0200 Subject: [PATCH 02/13] add optional topica menu when categories are active --- .../components/FilterMenu/CategoriesMenu.vue | 58 +++++++++++++++++++ webapp/components/FilterMenu/FilterMenu.vue | 8 --- webapp/layouts/default.vue | 10 ++++ 3 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 webapp/components/FilterMenu/CategoriesMenu.vue diff --git a/webapp/components/FilterMenu/CategoriesMenu.vue b/webapp/components/FilterMenu/CategoriesMenu.vue new file mode 100644 index 000000000..f8a224003 --- /dev/null +++ b/webapp/components/FilterMenu/CategoriesMenu.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/webapp/components/FilterMenu/FilterMenu.vue b/webapp/components/FilterMenu/FilterMenu.vue index 84c7c1f67..9e211ccf9 100644 --- a/webapp/components/FilterMenu/FilterMenu.vue +++ b/webapp/components/FilterMenu/FilterMenu.vue @@ -14,7 +14,6 @@

{{ $t('filter-menu.filter-by') }}

-

{{ $t('filter-menu.order-by') }}

@@ -29,24 +28,17 @@ import Dropdown from '~/components/Dropdown' import { mapGetters } from 'vuex' import FollowingFilter from './FollowingFilter' import OrderByFilter from './OrderByFilter' -import CategoriesFilter from './CategoriesFilter' export default { components: { Dropdown, FollowingFilter, - CategoriesFilter, OrderByFilter, }, props: { placement: { type: String }, offset: { type: [String, Number] }, }, - data() { - return { - categoriesActive: this.$env.CATEGORIES_ACTIVE, - } - }, computed: { ...mapGetters({ filterActive: 'posts/isActive', diff --git a/webapp/layouts/default.vue b/webapp/layouts/default.vue index 0dfd752bf..97b070d11 100644 --- a/webapp/layouts/default.vue +++ b/webapp/layouts/default.vue @@ -15,6 +15,13 @@ > + + + Date: Thu, 1 Sep 2022 10:31:53 +0200 Subject: [PATCH 03/13] Create GraphQL-Playground.md --- backend/src/graphql/GraphQL-Playground.md | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 backend/src/graphql/GraphQL-Playground.md diff --git a/backend/src/graphql/GraphQL-Playground.md b/backend/src/graphql/GraphQL-Playground.md new file mode 100644 index 000000000..3381f4e9e --- /dev/null +++ b/backend/src/graphql/GraphQL-Playground.md @@ -0,0 +1,28 @@ +# GraphQL Playground + +To use the GraphQL Playground we have to know some basics: + +## How To Login? + +At first we have to have a user of ocelot.social as whom we can login. +The user can be created by seeding the Neo4j database from the backend or by several GraphQL mutations. + +### Seed The Neo4j Database + +In your browser you reach the GraphQL Playground under `http://localhost:4000/` +if the database and the backend is running, see [backend](../../backend/README.md). +You can find how to seed there as well. + +### Use GraphQL Mutations To Create A User + +TODO: Describe how to create a user by GraphQL mutations! + +### Login Via GraphQL + +You can login by sending the query: + +```gql +mutation ($email: String!, $password: String!) { + login(email: $email, password: $password) +} +``` From 1f6beffa6f23edde1241eda1758f9fef224285f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 1 Sep 2022 10:32:36 +0200 Subject: [PATCH 04/13] Create GraphQL-Playground.md --- backend/src/GraphQL-Playground.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 backend/src/GraphQL-Playground.md diff --git a/backend/src/GraphQL-Playground.md b/backend/src/GraphQL-Playground.md new file mode 100644 index 000000000..3381f4e9e --- /dev/null +++ b/backend/src/GraphQL-Playground.md @@ -0,0 +1,28 @@ +# GraphQL Playground + +To use the GraphQL Playground we have to know some basics: + +## How To Login? + +At first we have to have a user of ocelot.social as whom we can login. +The user can be created by seeding the Neo4j database from the backend or by several GraphQL mutations. + +### Seed The Neo4j Database + +In your browser you reach the GraphQL Playground under `http://localhost:4000/` +if the database and the backend is running, see [backend](../../backend/README.md). +You can find how to seed there as well. + +### Use GraphQL Mutations To Create A User + +TODO: Describe how to create a user by GraphQL mutations! + +### Login Via GraphQL + +You can login by sending the query: + +```gql +mutation ($email: String!, $password: String!) { + login(email: $email, password: $password) +} +``` From 9ac943d11d48b613ab565c8267017182ebd7d426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 1 Sep 2022 10:57:16 +0200 Subject: [PATCH 05/13] Delete GraphQL-Playground.md --- backend/src/GraphQL-Playground.md | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 backend/src/GraphQL-Playground.md diff --git a/backend/src/GraphQL-Playground.md b/backend/src/GraphQL-Playground.md deleted file mode 100644 index 3381f4e9e..000000000 --- a/backend/src/GraphQL-Playground.md +++ /dev/null @@ -1,28 +0,0 @@ -# GraphQL Playground - -To use the GraphQL Playground we have to know some basics: - -## How To Login? - -At first we have to have a user of ocelot.social as whom we can login. -The user can be created by seeding the Neo4j database from the backend or by several GraphQL mutations. - -### Seed The Neo4j Database - -In your browser you reach the GraphQL Playground under `http://localhost:4000/` -if the database and the backend is running, see [backend](../../backend/README.md). -You can find how to seed there as well. - -### Use GraphQL Mutations To Create A User - -TODO: Describe how to create a user by GraphQL mutations! - -### Login Via GraphQL - -You can login by sending the query: - -```gql -mutation ($email: String!, $password: String!) { - login(email: $email, password: $password) -} -``` From 13cd81fcf5a8e6493e79bce6f63aa03cb9d97b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 1 Sep 2022 12:06:28 +0200 Subject: [PATCH 06/13] Update GraphQL-Playground.md --- backend/src/graphql/GraphQL-Playground.md | 100 +++++++++++++++++++--- 1 file changed, 90 insertions(+), 10 deletions(-) diff --git a/backend/src/graphql/GraphQL-Playground.md b/backend/src/graphql/GraphQL-Playground.md index 3381f4e9e..af248f112 100644 --- a/backend/src/graphql/GraphQL-Playground.md +++ b/backend/src/graphql/GraphQL-Playground.md @@ -1,28 +1,108 @@ # GraphQL Playground -To use the GraphQL Playground we have to know some basics: +To use GraphQL Playground, we need to know some basics: ## How To Login? -At first we have to have a user of ocelot.social as whom we can login. -The user can be created by seeding the Neo4j database from the backend or by several GraphQL mutations. +First, we need to have a user from ocelot.social to log in as. +The user can be created by seeding the Neo4j database from the backend or by multiple GraphQL mutations. ### Seed The Neo4j Database -In your browser you reach the GraphQL Playground under `http://localhost:4000/` -if the database and the backend is running, see [backend](../../backend/README.md). -You can find how to seed there as well. +In your browser you can reach the GraphQL Playground under `http://localhost:4000/`, if the database and the backend are running, see [backend](../../README.md). +There you will also find instructions on how to seed the database. ### Use GraphQL Mutations To Create A User -TODO: Describe how to create a user by GraphQL mutations! +TODO: Describe how to create a user using GraphQL mutations! ### Login Via GraphQL -You can login by sending the query: +You can register a user by sending the query: ```gql -mutation ($email: String!, $password: String!) { - login(email: $email, password: $password) +mutation { + login(email: "user@example.org", password: "1234") } ``` + +Or use `"moderator@example.org"` or `"admin@example.org"` for the roll you need. + +If all goes well, you will receive a QGL response like: + +```json +{ + "data": { + "login": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InUzIiwibmFtZSI6Ikplbm55IFJvc3RvY2siLCJzbHVnIjoiamVubnktcm9zdG9jayIsImlhdCI6MTY2MjAyMzMwNSwiZXhwIjoxNzI1MTM4NTA1LCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQwMDAiLCJzdWIiOiJ1MyJ9.atBS-SOeS784HPeFl_5s8sRWehEAU1BkgcOZFD8d4bU" + } +} +``` + +You can use this response to set an HTTP header when you click `HTTP HEADERS` in the footer. +Just set it with the login token you received in response: + +```json +{ + "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InUzIiwibmFtZSI6Ikplbm55IFJvc3RvY2siLCJzbHVnIjoiamVubnktcm9zdG9jayIsImlhdCI6MTY2MjAyMzMwNSwiZXhwIjoxNzI1MTM4NTA1LCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjQwMDAiLCJzdWIiOiJ1MyJ9.atBS-SOeS784HPeFl_5s8sRWehEAU1BkgcOZFD8d4bU" +} +``` + +This token is used for all other queries and mutations you send to the backend. + +## Query And Mutate + +When you are logged in and open a new playground tab by clicking "+", you can create a new group by sending the following mutation: + +```gql +mutation { + CreateGroup( + # id: "" + name: "My Group" + # slug: "" + about: "We will save the world" + description: "

English:

This group is hidden.

What is our group for?

This group was created to allow investigative journalists to share and collaborate.

How does it work?

Here you can internally share posts and comments about them.


Deutsch:

Diese Gruppe ist verborgen.

Wofür ist unsere Gruppe?

Diese Gruppe wurde geschaffen, um investigativen Journalisten den Austausch und die Zusammenarbeit zu ermöglichen.

Wie funktioniert das?

Hier könnt ihr euch intern über Beiträge und Kommentare zu ihnen austauschen.

" + groupType: hidden + actionRadius: interplanetary + categoryIds: ["cat12"] + ) { + id + name + slug + createdAt + updatedAt + disabled + deleted + about + description + groupType + actionRadius + myRole + } +} +``` + +You will receive the answer: + +```json +{ + "data": { + "CreateGroup": { + "id": "2e3bbadb-804b-4ebc-a673-2d7c7f05e827", + "name": "My Group", + "slug": "my-group", + "createdAt": "2022-09-01T09:44:47.969Z", + "updatedAt": "2022-09-01T09:44:47.969Z", + "disabled": false, + "deleted": false, + "about": "We will save the world", + "description": "

English:

This group is hidden.

What is our group for?

This group was created to allow investigative journalists to share and collaborate.

How does it work?

Here you can internally share posts and comments about them.


Deutsch:

Diese Gruppe ist verborgen.

Wofür ist unsere Gruppe?

Diese Gruppe wurde geschaffen, um investigativen Journalisten den Austausch und die Zusammenarbeit zu ermöglichen.

Wie funktioniert das?

Hier könnt ihr euch intern über Beiträge und Kommentare zu ihnen austauschen.

", + "groupType": "hidden", + "actionRadius": "interplanetary", + "myRole": "owner" + } + } +} +``` + +If you look into the Neo4j database with your browser and search the groups, you will now also find your new group. +For more details about our Neo4j database read [here](../../../neo4j/README.md). From 28a742574c889f4b850f0d3fcfdd4eee21b8f7d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 1 Sep 2022 12:15:30 +0200 Subject: [PATCH 07/13] Update README.md --- backend/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/README.md b/backend/README.md index 6d837856c..083606b09 100644 --- a/backend/README.md +++ b/backend/README.md @@ -60,6 +60,7 @@ your `.env` configuration file. Your backend is up and running at [http://localhost:4000/](http://localhost:4000/) This will start the GraphQL service \(by default on localhost:4000\) where you can issue GraphQL requests or access GraphQL Playground in the browser. +More details about our GraphQL playground and how to use it with ocelot.social can be found [here](./src/graphql/GraphQL-Playground.md). ![GraphQL Playground](../.gitbook/assets/graphql-playground.png) From b8ac4cc3ca33653fd529ae7b637418d4e06d76ef Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 5 Sep 2022 17:41:21 +0200 Subject: [PATCH 08/13] add saveCategoruSettings mutation to schema --- backend/src/middleware/permissionsMiddleware.js | 1 + backend/src/schema/types/type/User.gql | 2 ++ 2 files changed, 3 insertions(+) diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index b5ce4fe07..71a44f225 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -178,6 +178,7 @@ export default shield( GenerateInviteCode: isAuthenticated, switchUserRole: isAdmin, markTeaserAsViewed: allow, + saveCategorySettings: isAuthenticated, }, User: { email: or(isMyOwn, isAdmin), diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index 871e73ad8..b84606ff7 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -220,4 +220,6 @@ type Mutation { unblockUser(id: ID!): User switchUserRole(role: UserRole!, id: ID!): User + + saveCategorySettings(activeCategories: [String]): Boolean } From 572377acfde8e6a07f3fb32b598b4cf9b15b6969 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 5 Sep 2022 20:06:10 +0200 Subject: [PATCH 09/13] add active categories to user --- backend/src/schema/types/type/User.gql | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql index b84606ff7..d2ac79037 100644 --- a/backend/src/schema/types/type/User.gql +++ b/backend/src/schema/types/type/User.gql @@ -114,6 +114,14 @@ type User { badgesCount: Int! @cypher(statement: "MATCH (this)<-[:REWARDED]-(r:Badge) RETURN COUNT(r)") emotions: [EMOTED] + + activeCategories: [Category] @cypher( + statement: """ + MATCH (category:Category) + WHERE NOT ((this)-[:NOT_INTERESTED_IN]->(category)) + RETURN category + """ + ) } From fc6d544ea7399c711ba7ce5c6134cf0de94714ab Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 5 Sep 2022 20:07:14 +0200 Subject: [PATCH 10/13] add resolver for save active categories --- backend/src/schema/resolvers/users.js | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js index 5dc78c5e1..4ab721b06 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.js @@ -269,6 +269,46 @@ export default { session.close() } }, + saveCategorySettings: async (object, args, context, resolveInfo) => { + const { activeCategories } = args + const { + user: { id }, + } = context + + const session = context.driver.session() + await session.writeTransaction((transaction) => { + return transaction.run( + ` + MATCH (user:User { id: $id })-[previousCategories:NOT_INTERESTED_IN]->(category:Category) + DELETE previousCategories + RETURN user, category + `, + { id }, + ) + }) + + const writeTxResultPromise = session.writeTransaction(async (transaction) => { + const saveCategorySettingsResponse = await transaction.run( + ` + MATCH (category:Category) WHERE NOT category.id IN $activeCategories + MATCH (user:User { id: $id }) + MERGE (user)-[r:NOT_INTERESTED_IN]->(category) + RETURN user, r, category + `, + { id, activeCategories }, + ) + const [user] = await saveCategorySettingsResponse.records.map((record) => + record.get('user'), + ) + return user + }) + try { + await writeTxResultPromise + return true + } finally { + session.close() + } + }, }, User: { email: async (parent, params, context, resolveInfo) => { From 4e5d4cb8734a8f5c581e78cd7b4717d82fc27a8d Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Mon, 5 Sep 2022 20:51:48 +0200 Subject: [PATCH 11/13] basic tests for save category settings --- backend/src/schema/resolvers/users.js | 1 - backend/src/schema/resolvers/users.spec.js | 102 +++++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js index 4ab721b06..23a39a2a1 100644 --- a/backend/src/schema/resolvers/users.js +++ b/backend/src/schema/resolvers/users.js @@ -286,7 +286,6 @@ export default { { id }, ) }) - const writeTxResultPromise = session.writeTransaction(async (transaction) => { const saveCategorySettingsResponse = await transaction.run( ` diff --git a/backend/src/schema/resolvers/users.spec.js b/backend/src/schema/resolvers/users.spec.js index 920ef52ea..e655bdf28 100644 --- a/backend/src/schema/resolvers/users.spec.js +++ b/backend/src/schema/resolvers/users.spec.js @@ -3,6 +3,7 @@ import { gql } from '../../helpers/jest' import { getNeode, getDriver } from '../../db/neo4j' import createServer from '../../server' import { createTestClient } from 'apollo-server-testing' +import { categories } from '../../constants/categories' const categoryIds = ['cat9'] let user @@ -56,6 +57,12 @@ const switchUserRoleMutation = gql` } ` +const saveCategorySettings = gql` + mutation ($activeCategories: [String]) { + saveCategorySettings(activeCategories: $activeCategories) + } +` + beforeAll(async () => { await cleanDatabase() @@ -544,3 +551,98 @@ describe('switch user role', () => { }) }) }) + +describe('save category settings', () => { + beforeAll(async () => { + await Promise.all( + categories.map(({ icon, name }, index) => { + Factory.build('category', { + id: `cat${index + 1}`, + slug: name, + name, + icon, + }) + }), + ) + }) + + beforeEach(async () => { + user = await Factory.build('user', { + id: 'user', + role: 'user', + }) + variables = { + activeCategories: ['cat1', 'cat3', 'cat5'], + } + }) + + describe('not authenticated', () => { + beforeEach(async () => { + authenticatedUser = undefined + }) + + it('throws an error', async () => { + await expect(mutate({ mutation: saveCategorySettings, variables })).resolves.toEqual( + expect.objectContaining({ + errors: [ + expect.objectContaining({ + message: 'Not Authorized!', + }), + ], + }), + ) + }) + }) + + describe('authenticated', () => { + beforeEach(async () => { + authenticatedUser = await user.toJson() + }) + + describe('no categories saved', () => { + it('returns true for active categories mutation', async () => { + await expect(mutate({ mutation: saveCategorySettings, variables })).resolves.toEqual( + expect.objectContaining({ + data: { saveCategorySettings: true }, + }), + ) + }) + + describe('query for user', () => { + beforeEach(async () => { + await mutate({ mutation: saveCategorySettings, variables }) + }) + + it.skip('returns the active categories when user is queried', async () => { + const userQuery = gql` + query ($id: ID) { + User(id: $id) { + activeCategories { + id + } + } + } + ` + + await expect( + query({ query: userQuery, variables: { id: authenticatedUser.id } }), + ).resolves.toEqual( + expect.objectContaining({ + data: { + User: [ + { + activeCategories: expect.arrayContaining([ + { id: 'cat1' }, + { id: 'cat3' }, + { id: 'cat5' }, + ]), + }, + ], + }, + }), + ) + }) + }) + }) + }) +}) From 8a688ca78be0663527336f9b2502a3d796749308 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 6 Sep 2022 15:14:31 +0200 Subject: [PATCH 12/13] improve tests --- backend/src/schema/resolvers/users.spec.js | 72 ++++++++++++++++++---- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/backend/src/schema/resolvers/users.spec.js b/backend/src/schema/resolvers/users.spec.js index e655bdf28..7116d2201 100644 --- a/backend/src/schema/resolvers/users.spec.js +++ b/backend/src/schema/resolvers/users.spec.js @@ -553,7 +553,7 @@ describe('switch user role', () => { }) describe('save category settings', () => { - beforeAll(async () => { + beforeEach(async () => { await Promise.all( categories.map(({ icon, name }, index) => { Factory.build('category', { @@ -599,6 +599,16 @@ describe('save category settings', () => { authenticatedUser = await user.toJson() }) + const userQuery = gql` + query ($id: ID) { + User(id: $id) { + activeCategories { + id + } + } + } + ` + describe('no categories saved', () => { it('returns true for active categories mutation', async () => { await expect(mutate({ mutation: saveCategorySettings, variables })).resolves.toEqual( @@ -613,17 +623,7 @@ describe('save category settings', () => { await mutate({ mutation: saveCategorySettings, variables }) }) - it.skip('returns the active categories when user is queried', async () => { - const userQuery = gql` - query ($id: ID) { - User(id: $id) { - activeCategories { - id - } - } - } - ` - + it('returns the active categories when user is queried', async () => { await expect( query({ query: userQuery, variables: { id: authenticatedUser.id } }), ).resolves.toEqual( @@ -644,5 +644,53 @@ describe('save category settings', () => { }) }) }) + + describe('categories already saved', () => { + beforeEach(async () => { + variables = { + activeCategories: ['cat1', 'cat3', 'cat5'], + } + await mutate({ mutation: saveCategorySettings, variables }) + variables = { + activeCategories: ['cat10', 'cat11', 'cat12', 'cat8', 'cat9'], + } + }) + + it('returns true', async () => { + await expect(mutate({ mutation: saveCategorySettings, variables })).resolves.toEqual( + expect.objectContaining({ + data: { saveCategorySettings: true }, + }), + ) + }) + + describe('query for user', () => { + beforeEach(async () => { + await mutate({ mutation: saveCategorySettings, variables }) + }) + + it('returns the new active categories when user is queried', async () => { + await expect( + query({ query: userQuery, variables: { id: authenticatedUser.id } }), + ).resolves.toEqual( + expect.objectContaining({ + data: { + User: [ + { + activeCategories: expect.arrayContaining([ + { id: 'cat10' }, + { id: 'cat11' }, + { id: 'cat12' }, + { id: 'cat8' }, + { id: 'cat9' }, + ]), + }, + ], + }, + }), + ) + }) + }) + }) }) }) From f5d8014f6c8c414debbc378d6dea89fba250137d Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 7 Sep 2022 11:06:43 +0200 Subject: [PATCH 13/13] fix: Category Filter Menu Client Only --- webapp/components/FilterMenu/CategoriesMenu.vue | 6 +++--- webapp/layouts/default.vue | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/webapp/components/FilterMenu/CategoriesMenu.vue b/webapp/components/FilterMenu/CategoriesMenu.vue index f8a224003..37bd19c84 100644 --- a/webapp/components/FilterMenu/CategoriesMenu.vue +++ b/webapp/components/FilterMenu/CategoriesMenu.vue @@ -1,5 +1,5 @@