mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Merge branch '5059-groups/5131-implement-group-gql-model-and-crud' into 5140-My-Groups-Page
This commit is contained in:
commit
dc2f5f255d
5
backend/src/constants/categories.js
Normal file
5
backend/src/constants/categories.js
Normal file
@ -0,0 +1,5 @@
|
||||
// this file is duplicated in `backend/src/config/metadata.js` and `webapp/constants/metadata.js`
|
||||
export default {
|
||||
CATEGORIES_MIN: 1,
|
||||
CATEGORIES_MAX: 3,
|
||||
}
|
||||
@ -4,13 +4,13 @@ import gql from 'graphql-tag'
|
||||
|
||||
export const createGroupMutation = gql`
|
||||
mutation (
|
||||
$id: ID,
|
||||
$name: String!,
|
||||
$slug: String,
|
||||
$about: String,
|
||||
$description: String!,
|
||||
$groupType: GroupType!,
|
||||
$actionRadius: GroupActionRadius!,
|
||||
$id: ID
|
||||
$name: String!
|
||||
$slug: String
|
||||
$about: String
|
||||
$description: String!
|
||||
$groupType: GroupType!
|
||||
$actionRadius: GroupActionRadius!
|
||||
$categoryIds: [ID]
|
||||
) {
|
||||
CreateGroup(
|
||||
@ -47,13 +47,13 @@ export const createGroupMutation = gql`
|
||||
export const groupQuery = gql`
|
||||
query (
|
||||
$isMember: Boolean
|
||||
$id: ID,
|
||||
$name: String,
|
||||
$slug: String,
|
||||
$id: ID
|
||||
$name: String
|
||||
$slug: String
|
||||
$createdAt: String
|
||||
$updatedAt: String
|
||||
$about: String,
|
||||
$description: String,
|
||||
$about: String
|
||||
$description: String
|
||||
# $groupType: GroupType!,
|
||||
# $actionRadius: GroupActionRadius!,
|
||||
# $categoryIds: [ID]
|
||||
@ -93,6 +93,12 @@ export const groupQuery = gql`
|
||||
groupType
|
||||
actionRadius
|
||||
myRole
|
||||
categories {
|
||||
id
|
||||
slug
|
||||
name
|
||||
icon
|
||||
}
|
||||
# Wolle: owner {
|
||||
# name
|
||||
# }
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
// TODO: can be replaced with, which is no a fake:
|
||||
// TODO: can be replaced with: (which is no a fake)
|
||||
// import gql from 'graphql-tag'
|
||||
// See issue: https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/5152
|
||||
|
||||
//* This is a fake ES2015 template string, just to benefit of syntax
|
||||
// highlighting of `gql` template strings in certain editors.
|
||||
|
||||
@ -3,6 +3,7 @@ import { v4 as uuid } from 'uuid'
|
||||
// Wolle: import { isEmpty } from 'lodash'
|
||||
import { UserInputError } from 'apollo-server'
|
||||
import CONFIG from '../../config'
|
||||
import categories from '../../constants/categories'
|
||||
// Wolle: import { mergeImage, deleteImage } from './images/images'
|
||||
import Resolver from './helpers/Resolver'
|
||||
// Wolle: import { filterForMutedUsers } from './helpers/filterForMutedUsers'
|
||||
@ -69,6 +70,12 @@ export default {
|
||||
CreateGroup: async (_parent, params, context, _resolveInfo) => {
|
||||
const { categoryIds } = params
|
||||
delete params.categoryIds
|
||||
if (!categoryIds || categoryIds.length < categories.CATEGORIES_MIN) {
|
||||
throw new UserInputError('To Less Categories!')
|
||||
}
|
||||
if (categoryIds && categoryIds.length > categories.CATEGORIES_MAX) {
|
||||
throw new UserInputError('To Many Categories!')
|
||||
}
|
||||
params.id = params.id || uuid()
|
||||
const session = context.driver.session()
|
||||
const writeTxResultPromise = session.writeTransaction(async (transaction) => {
|
||||
|
||||
@ -52,21 +52,25 @@ beforeEach(async () => {
|
||||
neode.create('Category', {
|
||||
id: 'cat9',
|
||||
name: 'Democracy & Politics',
|
||||
slug: 'democracy-politics',
|
||||
icon: 'university',
|
||||
}),
|
||||
neode.create('Category', {
|
||||
id: 'cat4',
|
||||
name: 'Environment & Nature',
|
||||
slug: 'environment-nature',
|
||||
icon: 'tree',
|
||||
}),
|
||||
neode.create('Category', {
|
||||
id: 'cat15',
|
||||
name: 'Consumption & Sustainability',
|
||||
slug: 'consumption-sustainability',
|
||||
icon: 'shopping-cart',
|
||||
}),
|
||||
neode.create('Category', {
|
||||
id: 'cat27',
|
||||
name: 'Animal Protection',
|
||||
slug: 'animal-protection',
|
||||
icon: 'paw',
|
||||
}),
|
||||
])
|
||||
@ -133,44 +137,8 @@ describe('Group', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('query can fetch', () => {
|
||||
it('groups where user is member (or owner in this case)', async () => {
|
||||
const expected = {
|
||||
data: {
|
||||
Group: [
|
||||
{
|
||||
id: 'my-group',
|
||||
slug: 'the-best-group',
|
||||
myRole: 'owner',
|
||||
},
|
||||
],
|
||||
},
|
||||
errors: undefined,
|
||||
}
|
||||
await expect(
|
||||
query({ query: groupQuery, variables: { isMember: true } }),
|
||||
).resolves.toMatchObject(expected)
|
||||
})
|
||||
|
||||
it('groups where user is not(!) member', async () => {
|
||||
const expected = {
|
||||
data: {
|
||||
Group: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: 'others-group',
|
||||
slug: 'uninteresting-group',
|
||||
myRole: null,
|
||||
}),
|
||||
]),
|
||||
},
|
||||
errors: undefined,
|
||||
}
|
||||
await expect(
|
||||
query({ query: groupQuery, variables: { isMember: false } }),
|
||||
).resolves.toMatchObject(expected)
|
||||
})
|
||||
|
||||
it('all groups', async () => {
|
||||
describe('can find', () => {
|
||||
it('all', async () => {
|
||||
const expected = {
|
||||
data: {
|
||||
Group: expect.arrayContaining([
|
||||
@ -190,164 +158,200 @@ describe('Group', () => {
|
||||
}
|
||||
await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject(expected)
|
||||
})
|
||||
|
||||
it('where user is member (or owner in this case)', async () => {
|
||||
const expected = {
|
||||
data: {
|
||||
Group: [
|
||||
{
|
||||
id: 'my-group',
|
||||
slug: 'the-best-group',
|
||||
myRole: 'owner',
|
||||
},
|
||||
],
|
||||
},
|
||||
errors: undefined,
|
||||
}
|
||||
await expect(
|
||||
query({ query: groupQuery, variables: { isMember: true } }),
|
||||
).resolves.toMatchObject(expected)
|
||||
})
|
||||
|
||||
it('where user is not(!) member', async () => {
|
||||
const expected = {
|
||||
data: {
|
||||
Group: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: 'others-group',
|
||||
slug: 'uninteresting-group',
|
||||
myRole: null,
|
||||
}),
|
||||
]),
|
||||
},
|
||||
errors: undefined,
|
||||
}
|
||||
await expect(
|
||||
query({ query: groupQuery, variables: { isMember: false } }),
|
||||
).resolves.toMatchObject(expected)
|
||||
})
|
||||
})
|
||||
|
||||
// Wolle: describe('can be filtered', () => {
|
||||
// let followedUser, happyPost, cryPost
|
||||
// beforeEach(async () => {
|
||||
// ;[followedUser] = await Promise.all([
|
||||
// Factory.build(
|
||||
// 'user',
|
||||
// {
|
||||
// id: 'followed-by-me',
|
||||
// name: 'Followed User',
|
||||
// },
|
||||
// {
|
||||
// email: 'followed@example.org',
|
||||
// password: '1234',
|
||||
// },
|
||||
// ),
|
||||
// ])
|
||||
// ;[happyPost, cryPost] = await Promise.all([
|
||||
// Factory.build('post', { id: 'happy-post' }, { categoryIds: ['cat4'] }),
|
||||
// Factory.build('post', { id: 'cry-post' }, { categoryIds: ['cat15'] }),
|
||||
// Factory.build(
|
||||
// 'post',
|
||||
// {
|
||||
// id: 'post-by-followed-user',
|
||||
// },
|
||||
// {
|
||||
// categoryIds: ['cat9'],
|
||||
// author: followedUser,
|
||||
// },
|
||||
// ),
|
||||
// ])
|
||||
// })
|
||||
// describe('no filter', () => {
|
||||
// it('returns all posts', async () => {
|
||||
// const postQueryNoFilters = gql`
|
||||
// query Post($filter: _PostFilter) {
|
||||
// Post(filter: $filter) {
|
||||
// id
|
||||
// }
|
||||
// }
|
||||
// `
|
||||
// const expected = [{ id: 'happy-post' }, { id: 'cry-post' }, { id: 'post-by-followed-user' }]
|
||||
// variables = { filter: {} }
|
||||
// await expect(query({ query: postQueryNoFilters, variables })).resolves.toMatchObject({
|
||||
// data: {
|
||||
// Post: expect.arrayContaining(expected),
|
||||
// },
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// /* it('by categories', async () => {
|
||||
// const postQueryFilteredByCategories = gql`
|
||||
// query Post($filter: _PostFilter) {
|
||||
// Post(filter: $filter) {
|
||||
// id
|
||||
// categories {
|
||||
// id
|
||||
// }
|
||||
// }
|
||||
// describe('can be filtered', () => {
|
||||
// Wolle: it('by categories', async () => {
|
||||
// const postQueryFilteredByCategories = gql`
|
||||
// query Post($filter: _PostFilter) {
|
||||
// Post(filter: $filter) {
|
||||
// id
|
||||
// categories {
|
||||
// id
|
||||
// }
|
||||
// `
|
||||
// const expected = {
|
||||
// data: {
|
||||
// Post: [
|
||||
// {
|
||||
// id: 'post-by-followed-user',
|
||||
// categories: [{ id: 'cat9' }],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// }
|
||||
// variables = { ...variables, filter: { categories_some: { id_in: ['cat9'] } } }
|
||||
// await expect(
|
||||
// query({ query: postQueryFilteredByCategories, variables }),
|
||||
// ).resolves.toMatchObject(expected)
|
||||
// }) */
|
||||
// describe('by emotions', () => {
|
||||
// const postQueryFilteredByEmotions = gql`
|
||||
// query Post($filter: _PostFilter) {
|
||||
// Post(filter: $filter) {
|
||||
// id
|
||||
// emotions {
|
||||
// emotion
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// `
|
||||
// const expected = {
|
||||
// data: {
|
||||
// Post: [
|
||||
// {
|
||||
// id: 'post-by-followed-user',
|
||||
// categories: [{ id: 'cat9' }],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// }
|
||||
// variables = { ...variables, filter: { categories_some: { id_in: ['cat9'] } } }
|
||||
// await expect(
|
||||
// query({ query: postQueryFilteredByCategories, variables }),
|
||||
// ).resolves.toMatchObject(expected)
|
||||
// })
|
||||
// Wolle: let followedUser, happyPost, cryPost
|
||||
// beforeEach(async () => {
|
||||
// ;[followedUser] = await Promise.all([
|
||||
// Factory.build(
|
||||
// 'user',
|
||||
// {
|
||||
// id: 'followed-by-me',
|
||||
// name: 'Followed User',
|
||||
// },
|
||||
// {
|
||||
// email: 'followed@example.org',
|
||||
// password: '1234',
|
||||
// },
|
||||
// ),
|
||||
// ])
|
||||
// ;[happyPost, cryPost] = await Promise.all([
|
||||
// Factory.build('post', { id: 'happy-post' }, { categoryIds: ['cat4'] }),
|
||||
// Factory.build('post', { id: 'cry-post' }, { categoryIds: ['cat15'] }),
|
||||
// Factory.build(
|
||||
// 'post',
|
||||
// {
|
||||
// id: 'post-by-followed-user',
|
||||
// },
|
||||
// {
|
||||
// categoryIds: ['cat9'],
|
||||
// author: followedUser,
|
||||
// },
|
||||
// ),
|
||||
// ])
|
||||
// })
|
||||
// describe('no filter', () => {
|
||||
// it('returns all posts', async () => {
|
||||
// const postQueryNoFilters = gql`
|
||||
// query Post($filter: _PostFilter) {
|
||||
// Post(filter: $filter) {
|
||||
// id
|
||||
// }
|
||||
// `
|
||||
// it('filters by single emotion', async () => {
|
||||
// const expected = {
|
||||
// data: {
|
||||
// Post: [
|
||||
// {
|
||||
// id: 'happy-post',
|
||||
// emotions: [{ emotion: 'happy' }],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// }
|
||||
// `
|
||||
// const expected = [{ id: 'happy-post' }, { id: 'cry-post' }, { id: 'post-by-followed-user' }]
|
||||
// variables = { filter: {} }
|
||||
// await expect(query({ query: postQueryNoFilters, variables })).resolves.toMatchObject({
|
||||
// data: {
|
||||
// Post: expect.arrayContaining(expected),
|
||||
// },
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// describe('by emotions', () => {
|
||||
// const postQueryFilteredByEmotions = gql`
|
||||
// query Post($filter: _PostFilter) {
|
||||
// Post(filter: $filter) {
|
||||
// id
|
||||
// emotions {
|
||||
// emotion
|
||||
// }
|
||||
// await user.relateTo(happyPost, 'emoted', { emotion: 'happy' })
|
||||
// variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy'] } } }
|
||||
// await expect(
|
||||
// query({ query: postQueryFilteredByEmotions, variables }),
|
||||
// ).resolves.toMatchObject(expected)
|
||||
// })
|
||||
// it('filters by multiple emotions', async () => {
|
||||
// const expected = [
|
||||
// }
|
||||
// }
|
||||
// `
|
||||
// it('filters by single emotion', async () => {
|
||||
// const expected = {
|
||||
// data: {
|
||||
// Post: [
|
||||
// {
|
||||
// id: 'happy-post',
|
||||
// emotions: [{ emotion: 'happy' }],
|
||||
// },
|
||||
// {
|
||||
// id: 'cry-post',
|
||||
// emotions: [{ emotion: 'cry' }],
|
||||
// },
|
||||
// ]
|
||||
// await user.relateTo(happyPost, 'emoted', { emotion: 'happy' })
|
||||
// await user.relateTo(cryPost, 'emoted', { emotion: 'cry' })
|
||||
// variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy', 'cry'] } } }
|
||||
// await expect(
|
||||
// query({ query: postQueryFilteredByEmotions, variables }),
|
||||
// ).resolves.toMatchObject({
|
||||
// data: {
|
||||
// Post: expect.arrayContaining(expected),
|
||||
// },
|
||||
// errors: undefined,
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// it('by followed-by', async () => {
|
||||
// const postQueryFilteredByUsersFollowed = gql`
|
||||
// query Post($filter: _PostFilter) {
|
||||
// Post(filter: $filter) {
|
||||
// id
|
||||
// author {
|
||||
// id
|
||||
// name
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// `
|
||||
// await user.relateTo(followedUser, 'following')
|
||||
// variables = { filter: { author: { followedBy_some: { id: 'current-user' } } } }
|
||||
// await expect(
|
||||
// query({ query: postQueryFilteredByUsersFollowed, variables }),
|
||||
// ).resolves.toMatchObject({
|
||||
// data: {
|
||||
// Post: [
|
||||
// {
|
||||
// id: 'post-by-followed-user',
|
||||
// author: { id: 'followed-by-me', name: 'Followed User' },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// errors: undefined,
|
||||
// })
|
||||
// ],
|
||||
// },
|
||||
// }
|
||||
// await user.relateTo(happyPost, 'emoted', { emotion: 'happy' })
|
||||
// variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy'] } } }
|
||||
// await expect(
|
||||
// query({ query: postQueryFilteredByEmotions, variables }),
|
||||
// ).resolves.toMatchObject(expected)
|
||||
// })
|
||||
// it('filters by multiple emotions', async () => {
|
||||
// const expected = [
|
||||
// {
|
||||
// id: 'happy-post',
|
||||
// emotions: [{ emotion: 'happy' }],
|
||||
// },
|
||||
// {
|
||||
// id: 'cry-post',
|
||||
// emotions: [{ emotion: 'cry' }],
|
||||
// },
|
||||
// ]
|
||||
// await user.relateTo(happyPost, 'emoted', { emotion: 'happy' })
|
||||
// await user.relateTo(cryPost, 'emoted', { emotion: 'cry' })
|
||||
// variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy', 'cry'] } } }
|
||||
// await expect(
|
||||
// query({ query: postQueryFilteredByEmotions, variables }),
|
||||
// ).resolves.toMatchObject({
|
||||
// data: {
|
||||
// Post: expect.arrayContaining(expected),
|
||||
// },
|
||||
// errors: undefined,
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// it('by followed-by', async () => {
|
||||
// const postQueryFilteredByUsersFollowed = gql`
|
||||
// query Post($filter: _PostFilter) {
|
||||
// Post(filter: $filter) {
|
||||
// id
|
||||
// author {
|
||||
// id
|
||||
// name
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// `
|
||||
// await user.relateTo(followedUser, 'following')
|
||||
// variables = { filter: { author: { followedBy_some: { id: 'current-user' } } } }
|
||||
// await expect(
|
||||
// query({ query: postQueryFilteredByUsersFollowed, variables }),
|
||||
// ).resolves.toMatchObject({
|
||||
// data: {
|
||||
// Post: [
|
||||
// {
|
||||
// id: 'post-by-followed-user',
|
||||
// author: { id: 'followed-by-me', name: 'Followed User' },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// errors: undefined,
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
})
|
||||
})
|
||||
|
||||
@ -412,12 +416,34 @@ describe('CreateGroup', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('`disabled` and `deleted` default to `false`', async () => {
|
||||
it('"disabled" and "deleted" default to "false"', async () => {
|
||||
const expected = { data: { CreateGroup: { disabled: false, deleted: false } } }
|
||||
await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject(
|
||||
expected,
|
||||
)
|
||||
})
|
||||
|
||||
describe('categories', () => {
|
||||
describe('not even one', () => {
|
||||
it('throws error: "To Less Categories!"', async () => {
|
||||
const { errors } = await mutate({
|
||||
mutation: createGroupMutation,
|
||||
variables: { ...variables, categoryIds: null },
|
||||
})
|
||||
expect(errors[0]).toHaveProperty('message', 'To Less Categories!')
|
||||
})
|
||||
})
|
||||
|
||||
describe('four', () => {
|
||||
it('throws error: "To Many Categories!"', async () => {
|
||||
const { errors } = await mutate({
|
||||
mutation: createGroupMutation,
|
||||
variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] },
|
||||
})
|
||||
expect(errors[0]).toHaveProperty('message', 'To Many Categories!')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -141,6 +141,14 @@ input _GroupFilter {
|
||||
id_not: ID
|
||||
id_in: [ID!]
|
||||
id_not_in: [ID!]
|
||||
# categories: _CategoryFilter
|
||||
# categories_not: _CategoryFilter
|
||||
# categories_in: [_CategoryFilter!]
|
||||
# categories_not_in: [_CategoryFilter!]
|
||||
# categories_some: _CategoryFilter
|
||||
# categories_none: _CategoryFilter
|
||||
# categories_single: _CategoryFilter
|
||||
# categories_every: _CategoryFilter
|
||||
# Wolle:
|
||||
# friends: _GroupFilter
|
||||
# friends_not: _GroupFilter
|
||||
@ -185,7 +193,11 @@ type Query {
|
||||
filter: _GroupFilter
|
||||
): [Group]
|
||||
|
||||
availableGroupTypes: [GroupType]!
|
||||
AvailableGroupTypes: [GroupType]!
|
||||
|
||||
AvailableGroupActionRadii: [GroupActionRadius]!
|
||||
|
||||
AvailableGroupMemberRoles: [GroupMemberRole]!
|
||||
|
||||
# Wolle:
|
||||
# availableRoles: [UserRole]!
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user