diff --git a/backend/src/middleware/filterBubble/filterBubble.js b/backend/src/middleware/filterBubble/filterBubble.js
deleted file mode 100644
index bfdad5e2c..000000000
--- a/backend/src/middleware/filterBubble/filterBubble.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import replaceParams from './replaceParams'
-
-const replaceFilterBubbleParams = async (resolve, root, args, context, resolveInfo) => {
- args = await replaceParams(args, context)
- return resolve(root, args, context, resolveInfo)
-}
-
-export default {
- Query: {
- Post: replaceFilterBubbleParams,
- },
-}
diff --git a/backend/src/middleware/filterBubble/filterBubble.spec.js b/backend/src/middleware/filterBubble/filterBubble.spec.js
index afe1df1c9..62addeece 100644
--- a/backend/src/middleware/filterBubble/filterBubble.spec.js
+++ b/backend/src/middleware/filterBubble/filterBubble.spec.js
@@ -5,6 +5,7 @@ import Factory from '../../seed/factories'
const factory = Factory()
const currentUserParams = {
+ id: 'u1',
email: 'you@example.org',
name: 'This is you',
password: '1234',
@@ -41,7 +42,7 @@ afterEach(async () => {
await factory.cleanDatabase()
})
-describe('FilterBubble middleware', () => {
+describe('Filter posts by author is followed by sb.', () => {
describe('given an authenticated user', () => {
let authenticatedClient
@@ -52,7 +53,7 @@ describe('FilterBubble middleware', () => {
describe('no filter bubble', () => {
it('returns all posts', async () => {
- const query = '{ Post( filterBubble: {}) { title } }'
+ const query = '{ Post(filter: { }) { title } }'
const expected = {
Post: [
{ title: 'This is some random post' },
@@ -65,7 +66,7 @@ describe('FilterBubble middleware', () => {
describe('filtering for posts of followed users only', () => {
it('returns only posts authored by followed users', async () => {
- const query = '{ Post( filterBubble: { author: following }) { title } }'
+ const query = '{ Post( filter: { author: { followedBy_some: { id: "u1" } } }) { title } }'
const expected = {
Post: [{ title: 'This is the post of a followed user' }],
}
diff --git a/backend/src/middleware/filterBubble/replaceParams.js b/backend/src/middleware/filterBubble/replaceParams.js
deleted file mode 100644
index a10b6c29d..000000000
--- a/backend/src/middleware/filterBubble/replaceParams.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { UserInputError } from 'apollo-server'
-
-export default async function replaceParams(args, context) {
- const { author = 'all' } = args.filterBubble || {}
- const { user } = context
-
- if (author === 'following') {
- if (!user)
- throw new UserInputError(
- "You are unauthenticated - I don't know any users you are following.",
- )
-
- const session = context.driver.session()
- let { records } = await session.run(
- 'MATCH(followed:User)<-[:FOLLOWS]-(u {id: $userId}) RETURN followed.id',
- { userId: context.user.id },
- )
- const followedIds = records.map(record => record.get('followed.id'))
-
- // carefully override `id_in`
- args.filter = args.filter || {}
- args.filter.author = args.filter.author || {}
- args.filter.author.id_in = followedIds
-
- session.close()
- }
-
- delete args.filterBubble
-
- return args
-}
diff --git a/backend/src/middleware/filterBubble/replaceParams.spec.js b/backend/src/middleware/filterBubble/replaceParams.spec.js
deleted file mode 100644
index e14fda416..000000000
--- a/backend/src/middleware/filterBubble/replaceParams.spec.js
+++ /dev/null
@@ -1,129 +0,0 @@
-import replaceParams from './replaceParams.js'
-
-describe('replaceParams', () => {
- let args
- let context
- let run
-
- let action = () => {
- return replaceParams(args, context)
- }
-
- beforeEach(() => {
- args = {}
- run = jest.fn().mockResolvedValue({
- records: [{ get: () => 1 }, { get: () => 2 }, { get: () => 3 }],
- })
- context = {
- driver: {
- session: () => {
- return {
- run,
- close: () => {},
- }
- },
- },
- }
- })
-
- describe('args == ', () => {
- describe('{}', () => {
- it('does not crash', async () => {
- await expect(action()).resolves.toEqual({})
- })
- })
-
- describe('unauthenticated user', () => {
- beforeEach(() => {
- context.user = null
- })
-
- describe('{ filterBubble: { author: following } }', () => {
- it('throws error', async () => {
- args = { filterBubble: { author: 'following' } }
- await expect(action()).rejects.toThrow('You are unauthenticated')
- })
- })
-
- describe('{ filterBubble: { author: all } }', () => {
- it('removes filterBubble param', async () => {
- const expected = {}
- await expect(action()).resolves.toEqual(expected)
- })
-
- it('does not make database calls', async () => {
- await action()
- expect(run).not.toHaveBeenCalled()
- })
- })
- })
-
- describe('authenticated user', () => {
- beforeEach(() => {
- context.user = { id: 'u4711' }
- })
-
- describe('{ filterBubble: { author: following } }', () => {
- beforeEach(() => {
- args = { filterBubble: { author: 'following' } }
- })
-
- it('returns args object with resolved ids of followed users', async () => {
- const expected = { filter: { author: { id_in: [1, 2, 3] } } }
- await expect(action()).resolves.toEqual(expected)
- })
-
- it('makes database calls', async () => {
- await action()
- expect(run).toHaveBeenCalledTimes(1)
- })
-
- describe('given any additional filter args', () => {
- describe('merges', () => {
- it('empty filter object', async () => {
- args.filter = {}
- const expected = { filter: { author: { id_in: [1, 2, 3] } } }
- await expect(action()).resolves.toEqual(expected)
- })
-
- it('filter.title', async () => {
- args.filter = { title: 'bla' }
- const expected = { filter: { title: 'bla', author: { id_in: [1, 2, 3] } } }
- await expect(action()).resolves.toEqual(expected)
- })
-
- it('filter.author', async () => {
- args.filter = { author: { name: 'bla' } }
- const expected = { filter: { author: { name: 'bla', id_in: [1, 2, 3] } } }
- await expect(action()).resolves.toEqual(expected)
- })
- })
- })
- })
-
- describe('{ filterBubble: { } }', () => {
- it('removes filterBubble param', async () => {
- const expected = {}
- await expect(action()).resolves.toEqual(expected)
- })
-
- it('does not make database calls', async () => {
- await action()
- expect(run).not.toHaveBeenCalled()
- })
- })
-
- describe('{ filterBubble: { author: all } }', () => {
- it('removes filterBubble param', async () => {
- const expected = {}
- await expect(action()).resolves.toEqual(expected)
- })
-
- it('does not make database calls', async () => {
- await action()
- expect(run).not.toHaveBeenCalled()
- })
- })
- })
- })
-})
diff --git a/backend/src/middleware/index.js b/backend/src/middleware/index.js
index 6bc7be000..75314abc0 100644
--- a/backend/src/middleware/index.js
+++ b/backend/src/middleware/index.js
@@ -13,7 +13,6 @@ import includedFields from './includedFieldsMiddleware'
import orderBy from './orderByMiddleware'
import validation from './validation'
import notifications from './notifications'
-import filterBubble from './filterBubble/filterBubble'
export default schema => {
const middlewares = {
@@ -31,13 +30,11 @@ export default schema => {
user: user,
includedFields: includedFields,
orderBy: orderBy,
- filterBubble: filterBubble,
}
let order = [
'permissions',
'activityPub',
- 'filterBubble',
'password',
'dateTime',
'validation',
diff --git a/backend/src/schema/types/type/Post.gql b/backend/src/schema/types/type/Post.gql
index 1179c3e20..c402a1233 100644
--- a/backend/src/schema/types/type/Post.gql
+++ b/backend/src/schema/types/type/Post.gql
@@ -1,40 +1,3 @@
-enum FilterBubbleAuthorEnum {
- following
- all
-}
-
-input FilterBubble {
- author: FilterBubbleAuthorEnum
-}
-
-type Query {
- Post(
- id: ID
- activityId: String
- objectId: String
- title: String
- slug: String
- content: String
- contentExcerpt: String
- image: String
- imageUpload: Upload
- visibility: Visibility
- deleted: Boolean
- disabled: Boolean
- createdAt: String
- updatedAt: String
- commentsCount: Int
- shoutedCount: Int
- shoutedByCurrentUser: Boolean
- _id: String
- first: Int
- offset: Int
- orderBy: [_PostOrdering]
- filter: _PostFilter
- filterBubble: FilterBubble
- ): [Post]
-}
-
type Post {
id: ID!
activityId: String
diff --git a/webapp/components/FilterMenu/FilterMenu.spec.js b/webapp/components/FilterMenu/FilterMenu.spec.js
index c312a401b..030ad20da 100644
--- a/webapp/components/FilterMenu/FilterMenu.spec.js
+++ b/webapp/components/FilterMenu/FilterMenu.spec.js
@@ -9,9 +9,11 @@ localVue.use(Styleguide)
describe('FilterMenu.vue', () => {
let wrapper
let mocks
+ let propsData
const createWrapper = mountMethod => {
return mountMethod(FilterMenu, {
+ propsData,
mocks,
localVue,
})
@@ -19,35 +21,48 @@ describe('FilterMenu.vue', () => {
beforeEach(() => {
mocks = { $t: () => {} }
+ propsData = {}
})
- describe('mount', () => {
+ describe('given a user', () => {
beforeEach(() => {
- wrapper = createWrapper(mount)
+ propsData = {
+ user: {
+ id: '4711',
+ },
+ }
})
- it('renders a card', () => {
- expect(wrapper.is('.ds-card')).toBe(true)
- })
-
- describe('click "filter-by-followed-authors-only" button', () => {
- it('emits filterBubble object', () => {
- wrapper.find({ name: 'filter-by-followed-authors-only' }).trigger('click')
- expect(wrapper.emitted('changeFilterBubble')).toBeTruthy()
+ describe('mount', () => {
+ beforeEach(() => {
+ wrapper = createWrapper(mount)
})
- it('toggles filterBubble.author property', () => {
- wrapper.find({ name: 'filter-by-followed-authors-only' }).trigger('click')
- expect(wrapper.emitted('changeFilterBubble')[0]).toEqual([{ author: 'following' }])
- wrapper.find({ name: 'filter-by-followed-authors-only' }).trigger('click')
- expect(wrapper.emitted('changeFilterBubble')[1]).toEqual([{ author: 'all' }])
+ it('renders a card', () => {
+ expect(wrapper.is('.ds-card')).toBe(true)
})
- it('makes button primary', () => {
- wrapper.find({ name: 'filter-by-followed-authors-only' }).trigger('click')
- expect(
- wrapper.find({ name: 'filter-by-followed-authors-only' }).classes('ds-button-primary'),
- ).toBe(true)
+ describe('click "filter-by-followed-authors-only" button', () => {
+ it('emits filterBubble object', () => {
+ wrapper.find({ name: 'filter-by-followed-authors-only' }).trigger('click')
+ expect(wrapper.emitted('changeFilterBubble')).toBeTruthy()
+ })
+
+ it('toggles filterBubble.author property', () => {
+ wrapper.find({ name: 'filter-by-followed-authors-only' }).trigger('click')
+ expect(wrapper.emitted('changeFilterBubble')[0]).toEqual([
+ { author: { followedBy_some: { id: '4711' } } },
+ ])
+ wrapper.find({ name: 'filter-by-followed-authors-only' }).trigger('click')
+ expect(wrapper.emitted('changeFilterBubble')[1]).toEqual([{}])
+ })
+
+ it('makes button primary', () => {
+ wrapper.find({ name: 'filter-by-followed-authors-only' }).trigger('click')
+ expect(
+ wrapper.find({ name: 'filter-by-followed-authors-only' }).classes('ds-button-primary'),
+ ).toBe(true)
+ })
})
})
})
diff --git a/webapp/components/FilterMenu/FilterMenu.vue b/webapp/components/FilterMenu/FilterMenu.vue
index a2195a5fd..70dd3c236 100644
--- a/webapp/components/FilterMenu/FilterMenu.vue
+++ b/webapp/components/FilterMenu/FilterMenu.vue
@@ -11,7 +11,7 @@
@@ -22,24 +22,30 @@