From 8dff7496c0a3edb32d50755b0d625d4ec880260d Mon Sep 17 00:00:00 2001 From: roschaefer Date: Tue, 15 Oct 2019 14:17:36 +0200 Subject: [PATCH 01/56] refactor: create LoginForm component I moved most code in pages/login.vue to a separate LoginForm component. The intention is to have a separate vue storybook for the LoginForm component. --- webapp/components/LoginForm/LoginForm.vue | 129 ++++++++++++++++++++++ webapp/pages/login.vue | 121 +------------------- 2 files changed, 134 insertions(+), 116 deletions(-) create mode 100644 webapp/components/LoginForm/LoginForm.vue diff --git a/webapp/components/LoginForm/LoginForm.vue b/webapp/components/LoginForm/LoginForm.vue new file mode 100644 index 000000000..d72b5befe --- /dev/null +++ b/webapp/components/LoginForm/LoginForm.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/webapp/pages/login.vue b/webapp/pages/login.vue index 971754870..e969fe46f 100644 --- a/webapp/pages/login.vue +++ b/webapp/pages/login.vue @@ -1,138 +1,27 @@ - - From fced9ce4353a7ef459c7a7f81df1024764a7cf27 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Tue, 15 Oct 2019 14:19:26 +0200 Subject: [PATCH 02/56] refactor: remove `ready` quickfix in LoginForm According to the code comments this is a quick fix to avoid a visible re-arrangement of elements in the browser. To be honest: I would rather have the visible re-arrangement than this obscure quickfix. Everything that's visible and annoying will be fixed. Everything we just hide, we will forget. --- webapp/components/LoginForm/LoginForm.vue | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/webapp/components/LoginForm/LoginForm.vue b/webapp/components/LoginForm/LoginForm.vue index d72b5befe..0eb0d4be9 100644 --- a/webapp/components/LoginForm/LoginForm.vue +++ b/webapp/components/LoginForm/LoginForm.vue @@ -1,5 +1,5 @@ @@ -64,6 +66,7 @@ import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue' import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue' import { mapGetters } from 'vuex' import { filterPosts } from '~/graphql/PostQuery.js' +import PostMutations from '~/graphql/PostMutations' export default { components: { @@ -166,6 +169,37 @@ export default { return post.id !== deletedPost.id }) }, + resetPostList() { + this.offset = 0 + this.posts = [] + this.hasMore = true + }, + pinPost(post) { + this.$apollo + .mutate({ + mutation: PostMutations().UpdatePost, + variables: { id: post.id, title: post.title, content: post.content, pinned: true }, + }) + .then(() => { + this.$toast.success(this.$t('post.menu.pinnedSuccessfully')) + this.resetPostList() + this.$apollo.queries.Post.refetch() + }) + .catch(error => this.$toast.error(error.message)) + }, + unpinPost(post) { + this.$apollo + .mutate({ + mutation: PostMutations().UpdatePost, + variables: { id: post.id, title: post.title, content: post.content, unpinned: true }, + }) + .then(() => { + this.$toast.success(this.$t('post.menu.unpinnedSuccessfully')) + this.resetPostList() + this.$apollo.queries.Post.refetch() + }) + .catch(error => this.$toast.error(error.message)) + }, }, apollo: { Post: { @@ -176,7 +210,7 @@ export default { return { filter: this.finalFilters, first: this.pageSize, - orderBy: this.sorting, + orderBy: ['pinnedAt_asc', this.sorting], offset: 0, } }, diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 0cb26b62e..e2de1d15e 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -18,6 +18,8 @@ :resource="post" :modalsData="menuModalsData" :is-owner="isAuthor(post.author ? post.author.id : null)" + @pinPost="pinPost" + @unpinPost="unpinPost" /> @@ -77,6 +79,7 @@ From e37736500a6fe697bce9684972ae23351060989f Mon Sep 17 00:00:00 2001 From: mattwr18 Date: Fri, 18 Oct 2019 19:05:00 +0200 Subject: [PATCH 32/56] Move comment to above relevant code --- webapp/pages/post/_id/_slug/index.spec.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/webapp/pages/post/_id/_slug/index.spec.js b/webapp/pages/post/_id/_slug/index.spec.js index 369b0d29a..b5827db8d 100644 --- a/webapp/pages/post/_id/_slug/index.spec.js +++ b/webapp/pages/post/_id/_slug/index.spec.js @@ -31,10 +31,10 @@ describe('PostSlug', () => { $filters: { truncate: a => a, }, - // If you are mocking the router, then don't use VueRouter with localVue: https://vue-test-utils.vuejs.org/guides/using-with-vue-router.html $route: { hash: '', }, + // If you are mocking the router, then don't use VueRouter with localVue: https://vue-test-utils.vuejs.org/guides/using-with-vue-router.html $router: { history: { push: jest.fn(), @@ -47,9 +47,6 @@ describe('PostSlug', () => { $apollo: { mutate: jest.fn().mockResolvedValue(), }, - $route: { - hash: '', - }, } }) From 16d07bd3ba66e61c414787fcc8ac84e2920a3525 Mon Sep 17 00:00:00 2001 From: roschaefer Date: Fri, 18 Oct 2019 16:08:11 +0200 Subject: [PATCH 33/56] refactor: lint, frontend tests, vuex store This fixes the lint errors and failing frontend tests. Also, when the user chooses another orderBy, the menu gets translated. The refactoring moves code and complexity into the vuex store where it can be tested separately. --- .../FilterPosts/CategoriesFilterMenuItems.vue | 6 +- .../FilterPosts/FilterPosts.spec.js | 28 +++--- webapp/components/FilterPosts/FilterPosts.vue | 2 +- .../FilterPosts/GeneralFilterMenuItems.vue | 8 +- webapp/locales/de.json | 16 +++- webapp/locales/en.json | 16 +++- webapp/pages/index.spec.js | 28 +++++- webapp/pages/index.vue | 57 +++++-------- webapp/store/{postsFilter.js => posts.js} | 50 ++++++++--- .../{postsFilter.spec.js => posts.spec.js} | 85 +++++++++++++++---- 10 files changed, 197 insertions(+), 99 deletions(-) rename webapp/store/{postsFilter.js => posts.js} (69%) rename webapp/store/{postsFilter.spec.js => posts.spec.js} (63%) diff --git a/webapp/components/FilterPosts/CategoriesFilterMenuItems.vue b/webapp/components/FilterPosts/CategoriesFilterMenuItems.vue index 7a35bf3cc..72835a660 100644 --- a/webapp/components/FilterPosts/CategoriesFilterMenuItems.vue +++ b/webapp/components/FilterPosts/CategoriesFilterMenuItems.vue @@ -67,13 +67,13 @@ export default { }, computed: { ...mapGetters({ - filteredCategoryIds: 'postsFilter/filteredCategoryIds', + filteredCategoryIds: 'posts/filteredCategoryIds', }), }, methods: { ...mapMutations({ - resetCategories: 'postsFilter/RESET_CATEGORIES', - toggleCategory: 'postsFilter/TOGGLE_CATEGORY', + resetCategories: 'posts/RESET_CATEGORIES', + toggleCategory: 'posts/TOGGLE_CATEGORY', }), }, } diff --git a/webapp/components/FilterPosts/FilterPosts.spec.js b/webapp/components/FilterPosts/FilterPosts.spec.js index 0cbd3e962..1f0ee920d 100644 --- a/webapp/components/FilterPosts/FilterPosts.spec.js +++ b/webapp/components/FilterPosts/FilterPosts.spec.js @@ -50,20 +50,20 @@ describe('FilterPosts.vue', () => { describe('mount', () => { mutations = { - 'postsFilter/TOGGLE_FILTER_BY_FOLLOWED': jest.fn(), - 'postsFilter/RESET_CATEGORIES': jest.fn(), - 'postsFilter/TOGGLE_CATEGORY': jest.fn(), - 'postsFilter/TOGGLE_EMOTION': jest.fn(), + 'posts/TOGGLE_FILTER_BY_FOLLOWED': jest.fn(), + 'posts/RESET_CATEGORIES': jest.fn(), + 'posts/TOGGLE_CATEGORY': jest.fn(), + 'posts/TOGGLE_EMOTION': jest.fn(), } getters = { - 'postsFilter/isActive': () => false, + 'posts/isActive': () => false, 'auth/isModerator': () => false, 'auth/user': () => { return { id: 'u34' } }, - 'postsFilter/filteredCategoryIds': jest.fn(() => []), - 'postsFilter/filteredByUsersFollowed': jest.fn(), - 'postsFilter/filteredByEmotions': jest.fn(() => []), + 'posts/filteredCategoryIds': jest.fn(() => []), + 'posts/filteredByUsersFollowed': jest.fn(), + 'posts/filteredByEmotions': jest.fn(() => []), } const openFilterPosts = () => { const store = new Vuex.Store({ mutations, getters }) @@ -94,18 +94,18 @@ describe('FilterPosts.vue', () => { const wrapper = openFilterPosts() environmentAndNatureButton = wrapper.findAll('button').at(2) environmentAndNatureButton.trigger('click') - expect(mutations['postsFilter/TOGGLE_CATEGORY']).toHaveBeenCalledWith({}, 'cat4') + expect(mutations['posts/TOGGLE_CATEGORY']).toHaveBeenCalledWith({}, 'cat4') }) it('sets category button attribute `primary` when corresponding category is filtered', () => { - getters['postsFilter/filteredCategoryIds'] = jest.fn(() => ['cat9']) + getters['posts/filteredCategoryIds'] = jest.fn(() => ['cat9']) const wrapper = openFilterPosts() democracyAndPoliticsButton = wrapper.findAll('button').at(4) expect(democracyAndPoliticsButton.attributes().class).toContain('ds-button-primary') }) it('sets "filter-by-followed-authors-only" button attribute `primary`', () => { - getters['postsFilter/filteredByUsersFollowed'] = jest.fn(() => true) + getters['posts/filteredByUsersFollowed'] = jest.fn(() => true) const wrapper = openFilterPosts() expect( wrapper.find({ name: 'filter-by-followed-authors-only' }).classes('ds-button-primary'), @@ -120,7 +120,7 @@ describe('FilterPosts.vue', () => { }) it('calls TOGGLE_FILTER_BY_FOLLOWED', () => { - expect(mutations['postsFilter/TOGGLE_FILTER_BY_FOLLOWED']).toHaveBeenCalledWith({}, 'u34') + expect(mutations['posts/TOGGLE_FILTER_BY_FOLLOWED']).toHaveBeenCalledWith({}, 'u34') }) }) @@ -129,11 +129,11 @@ describe('FilterPosts.vue', () => { const wrapper = openFilterPosts() happyEmotionButton = wrapper.findAll('button.emotions-buttons').at(1) happyEmotionButton.trigger('click') - expect(mutations['postsFilter/TOGGLE_EMOTION']).toHaveBeenCalledWith({}, 'happy') + expect(mutations['posts/TOGGLE_EMOTION']).toHaveBeenCalledWith({}, 'happy') }) it('sets the attribute `src` to colorized image', () => { - getters['postsFilter/filteredByEmotions'] = jest.fn(() => ['happy']) + getters['posts/filteredByEmotions'] = jest.fn(() => ['happy']) const wrapper = openFilterPosts() happyEmotionButton = wrapper.findAll('button.emotions-buttons').at(1) const happyEmotionButtonImage = happyEmotionButton.find('img') diff --git a/webapp/components/FilterPosts/FilterPosts.vue b/webapp/components/FilterPosts/FilterPosts.vue index 8a12ac633..58f0794d2 100644 --- a/webapp/components/FilterPosts/FilterPosts.vue +++ b/webapp/components/FilterPosts/FilterPosts.vue @@ -39,7 +39,7 @@ export default { computed: { ...mapGetters({ currentUser: 'auth/user', - filterActive: 'postsFilter/isActive', + filterActive: 'posts/isActive', }), chunk() { return chunk(this.categories, 2) diff --git a/webapp/components/FilterPosts/GeneralFilterMenuItems.vue b/webapp/components/FilterPosts/GeneralFilterMenuItems.vue index 0c8db9d22..96b050713 100644 --- a/webapp/components/FilterPosts/GeneralFilterMenuItems.vue +++ b/webapp/components/FilterPosts/GeneralFilterMenuItems.vue @@ -68,14 +68,14 @@ export default { }, computed: { ...mapGetters({ - filteredByUsersFollowed: 'postsFilter/filteredByUsersFollowed', - filteredByEmotions: 'postsFilter/filteredByEmotions', + filteredByUsersFollowed: 'posts/filteredByUsersFollowed', + filteredByEmotions: 'posts/filteredByEmotions', }), }, methods: { ...mapMutations({ - toggleFilteredByFollowed: 'postsFilter/TOGGLE_FILTER_BY_FOLLOWED', - toogleFilteredByEmotions: 'postsFilter/TOGGLE_EMOTION', + toggleFilteredByFollowed: 'posts/TOGGLE_FILTER_BY_FOLLOWED', + toogleFilteredByEmotions: 'posts/TOGGLE_EMOTION', }), iconPath(emotion) { if (this.filteredByEmotions.includes(emotion)) { diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 9f10d929d..7ba85ddab 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -50,6 +50,18 @@ } } }, + "store": { + "posts": { + "orderBy": { + "newest": { + "label": "Neueste" + }, + "oldest": { + "label": "Älteste" + } + } + } + }, "maintenance": { "title": "Human Connection befindet sich in der Wartung", "explanation": "Zurzeit führen wir einige geplante Wartungsarbeiten durch, bitte versuch es später erneut.", @@ -95,10 +107,6 @@ "code-of-conduct": "Verhaltenscodex", "back-to-login": "Zurück zur Anmeldung" }, - "sorting": { - "newest": "Neueste", - "oldest": "Älteste" - }, "login": { "copy": "Wenn Du bereits ein Konto bei Human Connection hast, melde Dich bitte hier an.", "login": "Einloggen", diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 9860aa457..e752aa850 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -51,6 +51,18 @@ } } }, + "store": { + "posts": { + "orderBy": { + "newest": { + "label": "Newest" + }, + "oldest": { + "label": "Oldest" + } + } + } + }, "maintenance": { "title": "Human Connection is under maintenance", "explanation": "At the moment we are doing some scheduled maintenance, please try again later.", @@ -96,10 +108,6 @@ "code-of-conduct": "Code of Conduct", "back-to-login": "Back to login page" }, - "sorting": { - "newest": "Newest", - "oldest": "Oldest" - }, "login": { "copy": "If you already have a human-connection account, please login.", "login": "Login", diff --git a/webapp/pages/index.spec.js b/webapp/pages/index.spec.js index 5e38897c1..0433957bb 100644 --- a/webapp/pages/index.spec.js +++ b/webapp/pages/index.spec.js @@ -24,15 +24,37 @@ describe('PostIndex', () => { let Wrapper let store let mocks + let mutations beforeEach(() => { + mutations = { + 'posts/SELECT_ORDER': jest.fn(), + } store = new Vuex.Store({ getters: { - 'postsFilter/postsFilter': () => ({}), + 'posts/filter': () => ({}), + 'posts/orderOptions': () => () => [ + { + key: 'store.posts.orderBy.oldest.label', + label: 'store.posts.orderBy.oldest.label', + icon: 'sort-amount-asc', + value: 'createdAt_asc', + }, + { + key: 'store.posts.orderBy.newest.label', + label: 'store.posts.orderBy.newest.label', + icon: 'sort-amount-desc', + value: 'createdAt_desc', + }, + ], + 'posts/selectedOrder': () => () => 'createdAt_desc', + 'posts/orderIcon': () => 'sort-amount-desc', + 'posts/orderBy': () => 'createdAt_desc', 'auth/user': () => { return { id: 'u23' } }, }, + mutations, }) mocks = { $t: key => key, @@ -103,12 +125,12 @@ describe('PostIndex', () => { }) }) - it('sets the post in the store when there are posts', () => { + it('calls store when using order by menu', () => { wrapper .findAll('li') .at(0) .trigger('click') - expect(wrapper.vm.sorting).toEqual('createdAt_desc') + expect(mutations['posts/SELECT_ORDER']).toHaveBeenCalledWith({}, 'createdAt_asc') }) it('updates offset when a user clicks on the load more button', () => { diff --git a/webapp/pages/index.vue b/webapp/pages/index.vue index 2443bc037..ec3b02e4b 100644 --- a/webapp/pages/index.vue +++ b/webapp/pages/index.vue @@ -10,8 +10,7 @@ v-model="selected" :options="sortingOptions" size="large" - v-bind:icon-right="sortingIcon" - @input="updateOrder" + :icon-right="sortingIcon" > @@ -83,34 +82,29 @@ export default { offset: 0, pageSize: 12, hashtag, - sortingIcon: 'sort-amount-desc', - selected: this.$t('sorting.newest'), - sortingOptions: [ - { - label: this.$t('sorting.newest'), - value: 'Newest', - icons: 'sort-amount-desc', - order: 'createdAt_desc', - }, - { - label: this.$t('sorting.oldest'), - value: 'Oldest', - icons: 'sort-amount-asc', - order: 'createdAt_asc', - }, - ], - } - }, - mounted() { - if(this.postsOrder.label) { - this.selected = this.postsOrder.label } }, computed: { ...mapGetters({ - postsFilter: 'postsFilter/postsFilter', - postsOrder: 'postsFilter/postsOrder', + postsFilter: 'posts/filter', + orderOptions: 'posts/orderOptions', + orderBy: 'posts/orderBy', + selectedOrder: 'posts/selectedOrder', + sortingIcon: 'posts/orderIcon', }), + selected: { + get() { + return this.selectedOrder(this) + }, + set({ value }) { + this.offset = 0 + this.posts = [] + this.selectOrder(value) + }, + }, + sortingOptions() { + return this.orderOptions(this) + }, finalFilters() { let filter = this.postsFilter if (this.hashtag) { @@ -127,15 +121,8 @@ export default { }, methods: { ...mapMutations({ - setPostsOrder: 'postsFilter/UPDATE_ORDER', + selectOrder: 'posts/SELECT_ORDER', }), - updateOrder(sortingOptions) { - this.offset = 0 - this.posts = [] - this.sortingIcon = sortingOptions.icons - this.selected = sortingOptions.label - this.setPostsOrder(sortingOptions) - }, clearSearch() { this.$router.push({ path: '/' }) this.hashtag = null @@ -156,7 +143,7 @@ export default { offset: this.offset, filter: this.finalFilters, first: this.pageSize, - orderBy: this.sorting, + orderBy: this.orderBy, }, updateQuery: (previousResult, { fetchMoreResult }) => { if (!fetchMoreResult || fetchMoreResult.Post.length < this.pageSize) { @@ -184,7 +171,7 @@ export default { return { filter: this.finalFilters, first: this.pageSize, - orderBy: this.postsOrder.order, + orderBy: this.orderBy, offset: 0, } }, diff --git a/webapp/store/postsFilter.js b/webapp/store/posts.js similarity index 69% rename from webapp/store/postsFilter.js rename to webapp/store/posts.js index 8bdf1a238..97c0e1245 100644 --- a/webapp/store/postsFilter.js +++ b/webapp/store/posts.js @@ -7,17 +7,25 @@ import clone from 'lodash/clone' const defaultFilter = {} +const orderOptions = { + createdAt_asc: { + value: 'createdAt_asc', + key: 'store.posts.orderBy.oldest.label', + icon: 'sort-amount-asc', + }, + createdAt_desc: { + value: 'createdAt_desc', + key: 'store.posts.orderBy.newest.label', + icon: 'sort-amount-desc', + }, +} + export const state = () => { return { filter: { ...defaultFilter, }, - postsOrder: { - label: null, - value: 'Newest', - icons: 'sort-amount-desc', - order: 'createdAt_desc', - } + order: orderOptions['createdAt_desc'], } } @@ -52,16 +60,16 @@ export const mutations = { if (isEmpty(get(filter, 'emotions_some.emotion_in'))) delete filter.emotions_some state.filter = filter }, - UPDATE_ORDER(state, postsOrder) { - state.postsOrder = postsOrder - } + SELECT_ORDER(state, value) { + state.order = orderOptions[value] + }, } export const getters = { isActive(state) { return !isEqual(state.filter, defaultFilter) }, - postsFilter(state) { + filter(state) { return state.filter }, filteredCategoryIds(state) { @@ -73,7 +81,23 @@ export const getters = { filteredByEmotions(state) { return get(state.filter, 'emotions_some.emotion_in') || [] }, - postsOrder(state) { - return state.postsOrder - } + orderOptions: state => ({ $t }) => + Object.values(orderOptions).map(option => { + return { + ...option, + label: $t(option.key), + } + }), + selectedOrder: state => ({ $t }) => { + return { + ...state.order, + label: $t(state.order.key), + } + }, + orderBy(state) { + return state.order.value + }, + orderIcon(state) { + return state.order.icon + }, } diff --git a/webapp/store/postsFilter.spec.js b/webapp/store/posts.spec.js similarity index 63% rename from webapp/store/postsFilter.spec.js rename to webapp/store/posts.spec.js index 68a3dbd6e..536c4c924 100644 --- a/webapp/store/postsFilter.spec.js +++ b/webapp/store/posts.spec.js @@ -1,7 +1,7 @@ -import { getters, mutations } from './postsFilter.js' +import { getters, mutations } from './posts.js' let state -let testAction +let testMutation describe('getters', () => { describe('isActive', () => { @@ -25,10 +25,10 @@ describe('getters', () => { }) }) - describe('postsFilter', () => { + describe('filter', () => { it('returns filter', () => { state = { filter: { author: { followedBy_some: { id: 7 } } } } - expect(getters.postsFilter(state)).toEqual({ author: { followedBy_some: { id: 7 } } }) + expect(getters.filter(state)).toEqual({ author: { followedBy_some: { id: 7 } } }) }) }) @@ -67,14 +67,48 @@ describe('getters', () => { expect(getters.filteredByEmotions(state)).toEqual([]) }) }) + + describe('orderByOptions', () => { + it('returns all options regardless of current state', () => { + const $t = jest.fn(t => t) + expect(getters.orderOptions()({ $t })).toEqual([ + { + key: 'store.posts.orderBy.oldest.label', + label: 'store.posts.orderBy.oldest.label', + icon: 'sort-amount-asc', + value: 'createdAt_asc', + }, + { + key: 'store.posts.orderBy.newest.label', + label: 'store.posts.orderBy.newest.label', + icon: 'sort-amount-desc', + value: 'createdAt_desc', + }, + ]) + }) + }) + + describe('orderBy', () => { + it('returns value for graphql query', () => { + state = { + order: { + key: 'store.posts.orderBy.newest.label', + label: 'store.posts.orderBy.newest.label', + icon: 'sort-amount-desc', + value: 'createdAt_desc', + }, + } + expect(getters.orderBy(state)).toEqual('createdAt_desc') + }) + }) }) describe('mutations', () => { describe('RESET_CATEGORIES', () => { beforeEach(() => { - testAction = categoryId => { + testMutation = categoryId => { mutations.RESET_CATEGORIES(state, categoryId) - return getters.postsFilter(state) + return getters.filter(state) } }) it('resets the categories filter', () => { @@ -84,37 +118,37 @@ describe('mutations', () => { categories_some: { id_in: [23] }, }, } - expect(testAction(23)).toEqual({ author: { followedBy_some: { id: 7 } } }) + expect(testMutation(23)).toEqual({ author: { followedBy_some: { id: 7 } } }) }) }) describe('TOGGLE_CATEGORY', () => { beforeEach(() => { - testAction = categoryId => { + testMutation = categoryId => { mutations.TOGGLE_CATEGORY(state, categoryId) - return getters.postsFilter(state) + return getters.filter(state) } }) it('creates category filter if empty', () => { state = { filter: {} } - expect(testAction(23)).toEqual({ categories_some: { id_in: [23] } }) + expect(testMutation(23)).toEqual({ categories_some: { id_in: [23] } }) }) it('adds category id not present', () => { state = { filter: { categories_some: { id_in: [24] } } } - expect(testAction(23)).toEqual({ categories_some: { id_in: [24, 23] } }) + expect(testMutation(23)).toEqual({ categories_some: { id_in: [24, 23] } }) }) it('removes category id if present', () => { state = { filter: { categories_some: { id_in: [23, 24] } } } - const result = testAction(23) + const result = testMutation(23) expect(result).toEqual({ categories_some: { id_in: [24] } }) }) it('removes category filter if empty', () => { state = { filter: { categories_some: { id_in: [23] } } } - expect(testAction(23)).toEqual({}) + expect(testMutation(23)).toEqual({}) }) it('does not get in the way of other filters', () => { @@ -124,15 +158,15 @@ describe('mutations', () => { categories_some: { id_in: [23] }, }, } - expect(testAction(23)).toEqual({ author: { followedBy_some: { id: 7 } } }) + expect(testMutation(23)).toEqual({ author: { followedBy_some: { id: 7 } } }) }) }) describe('TOGGLE_FILTER_BY_FOLLOWED', () => { beforeEach(() => { - testAction = userId => { + testMutation = userId => { mutations.TOGGLE_FILTER_BY_FOLLOWED(state, userId) - return getters.postsFilter(state) + return getters.filter(state) } }) @@ -142,7 +176,7 @@ describe('mutations', () => { }) it('attaches the id of the current user to the filter object', () => { - expect(testAction(4711)).toEqual({ author: { followedBy_some: { id: 4711 } } }) + expect(testMutation(4711)).toEqual({ author: { followedBy_some: { id: 4711 } } }) }) }) @@ -152,8 +186,23 @@ describe('mutations', () => { }) it('remove the id of the current user from the filter object', () => { - expect(testAction(4711)).toEqual({}) + expect(testMutation(4711)).toEqual({}) }) }) }) + + describe('SELECT_ORDER', () => { + beforeEach(() => { + testMutation = key => { + mutations.SELECT_ORDER(state, key) + return getters.orderBy(state) + } + }) + it('switches the currently selected order', () => { + state = { + // does not matter + } + expect(testMutation('createdAt_asc')).toEqual('createdAt_asc') + }) + }) }) From cf5042d9a426a80cea2d726068be44de11cf7f50 Mon Sep 17 00:00:00 2001 From: aonomike Date: Sat, 19 Oct 2019 11:35:36 +0300 Subject: [PATCH 34/56] Refactor report resolver spec - Set up the apollo server testing - Refactor unauthenticated path for the mutation --- backend/src/schema/resolvers/reports.spec.js | 1063 ++++++++++-------- 1 file changed, 564 insertions(+), 499 deletions(-) diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.js index 4022be1b1..2c853d1fa 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.js @@ -1,521 +1,586 @@ -import { GraphQLClient } from 'graphql-request' -import Factory from '../../seed/factories' -import { host, login, gql } from '../../jest/helpers' -import { getDriver, neode } from '../../bootstrap/neo4j' import { createTestClient } from 'apollo-server-testing' import createServer from '../.././server' +import Factory from '../../seed/factories' +import { gql } from '../../jest/helpers' +import { getDriver, neode as getNeode } from '../../bootstrap/neo4j' const factory = Factory() -const instance = neode() +const instance = getNeode() const driver = getDriver() -describe('report mutation', () => { - let reportMutation - let headers - let client - let variables - let createPostVariables - let user - const categoryIds = ['cat9'] - - const action = () => { - reportMutation = gql` - mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { - report( - resourceId: $resourceId - reasonCategory: $reasonCategory - reasonDescription: $reasonDescription - ) { - createdAt - reasonCategory - reasonDescription - type - submitter { - email - } - user { - name - } - post { - title - } - comment { - content - } - } - } - ` - client = new GraphQLClient(host, { - headers, - }) - return client.request(reportMutation, variables) - } - - beforeEach(async () => { - variables = { - resourceId: 'whatever', - reasonCategory: 'other', - reasonDescription: 'Violates code of conduct !!!', - } - headers = {} - user = await factory.create('User', { - id: 'u1', - role: 'user', - email: 'test@example.org', - password: '1234', - }) - await factory.create('User', { - id: 'u2', - role: 'user', - name: 'abusive-user', - email: 'abusive-user@example.org', - }) - await instance.create('Category', { - id: 'cat9', - name: 'Democracy & Politics', - icon: 'university', - }) - }) - - afterEach(async () => { - await factory.cleanDatabase() - }) - - describe('unauthenticated', () => { - it('throws authorization error', async () => { - await expect(action()).rejects.toThrow('Not Authorised') - }) - }) - - describe('authenticated', () => { - beforeEach(async () => { - headers = await login({ - email: 'test@example.org', - password: '1234', - }) - }) - - describe('invalid resource id', () => { - it('returns null', async () => { - await expect(action()).resolves.toEqual({ - report: null, - }) - }) - }) - - describe('valid resource id', () => { - describe('reported resource is a user', () => { - beforeEach(async () => { - variables = { - ...variables, - resourceId: 'u2', - } - }) - - it('returns type "User"', async () => { - await expect(action()).resolves.toMatchObject({ - report: { - type: 'User', - }, - }) - }) - - it('returns resource in user attribute', async () => { - await expect(action()).resolves.toMatchObject({ - report: { - user: { - name: 'abusive-user', - }, - }, - }) - }) - - it('returns the submitter', async () => { - await expect(action()).resolves.toMatchObject({ - report: { - submitter: { - email: 'test@example.org', - }, - }, - }) - }) - - it('returns a date', async () => { - await expect(action()).resolves.toMatchObject({ - report: { - createdAt: expect.any(String), - }, - }) - }) - - it('returns the reason category', async () => { - variables = { - ...variables, - reasonCategory: 'criminal_behavior_violation_german_law', - } - await expect(action()).resolves.toMatchObject({ - report: { - reasonCategory: 'criminal_behavior_violation_german_law', - }, - }) - }) - - it('gives an error if the reason category is not in enum "ReasonCategory"', async () => { - variables = { - ...variables, - reasonCategory: 'my_category', - } - await expect(action()).rejects.toThrow( - 'got invalid value "my_category"; Expected type ReasonCategory', - ) - }) - - it('returns the reason description', async () => { - variables = { - ...variables, - reasonDescription: 'My reason!', - } - await expect(action()).resolves.toMatchObject({ - report: { - reasonDescription: 'My reason!', - }, - }) - }) - - it('sanitize the reason description', async () => { - variables = { - ...variables, - reasonDescription: 'My reason !', - } - await expect(action()).resolves.toMatchObject({ - report: { - reasonDescription: 'My reason !', - }, - }) - }) - }) - - describe('reported resource is a post', () => { - beforeEach(async () => { - await factory.create('Post', { - author: user, - id: 'p23', - title: 'Matt and Robert having a pair-programming', - categoryIds, - }) - variables = { - ...variables, - resourceId: 'p23', - } - }) - - it('returns type "Post"', async () => { - await expect(action()).resolves.toMatchObject({ - report: { - type: 'Post', - }, - }) - }) - - it('returns resource in post attribute', async () => { - await expect(action()).resolves.toMatchObject({ - report: { - post: { - title: 'Matt and Robert having a pair-programming', - }, - }, - }) - }) - - it('returns null in user attribute', async () => { - await expect(action()).resolves.toMatchObject({ - report: { - user: null, - }, - }) - }) - }) - - /* An der Stelle würde ich den p23 noch mal prüfen, diesmal muss aber eine error meldung kommen. - At this point I would check the p23 again, but this time there must be an error message. */ - - describe('reported resource is a comment', () => { - beforeEach(async () => { - createPostVariables = { - id: 'p1', - title: 'post to comment on', - content: 'please comment on me', - categoryIds, - } - await factory.create('Post', { ...createPostVariables, author: user }) - await factory.create('Comment', { - author: user, - postId: 'p1', - id: 'c34', - content: 'Robert getting tired.', - }) - variables = { - ...variables, - resourceId: 'c34', - } - }) - - it('returns type "Comment"', async () => { - await expect(action()).resolves.toMatchObject({ - report: { - type: 'Comment', - }, - }) - }) - - it('returns resource in comment attribute', async () => { - await expect(action()).resolves.toMatchObject({ - report: { - comment: { - content: 'Robert getting tired.', - }, - }, - }) - }) - }) - - /* An der Stelle würde ich den c34 noch mal prüfen, diesmal muss aber eine error meldung kommen. - At this point I would check the c34 again, but this time there must be an error message. */ - - describe('reported resource is a tag', () => { - beforeEach(async () => { - await factory.create('Tag', { - id: 't23', - }) - variables = { - ...variables, - resourceId: 't23', - } - }) - - it('returns null', async () => { - await expect(action()).resolves.toMatchObject({ - report: null, - }) - }) - }) - - /* An der Stelle würde ich den t23 noch mal prüfen, diesmal muss aber eine error meldung kommen. - At this point I would check the t23 again, but this time there must be an error message. */ - }) - }) -}) - -describe('reports query', () => { - let query, mutate, authenticatedUser, moderator, user, author - const categoryIds = ['cat9'] - +describe('report',()=>{ + let authenticatedUser, mutate, query const reportMutation = gql` - mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { - report( - resourceId: $resourceId - reasonCategory: $reasonCategory - reasonDescription: $reasonDescription - ) { - type + mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { + report( + resourceId: $resourceId + reasonCategory: $reasonCategory + reasonDescription: $reasonDescription + ) { + createdAt + reasonCategory + reasonDescription + type + submitter { + email + } + user { + name + } + post { + title + } + comment { + content } } - ` - const reportsQuery = gql` - query { - reports(orderBy: createdAt_desc) { - createdAt - reasonCategory - reasonDescription - submitter { - id - } - type - user { - id - } - post { - id - } - comment { - id - } - } - } - ` + } +` +const variables = { + resourceId: 'whatever', + reasonCategory: 'other', + reasonDescription: 'Violates code of conduct !!!', +} - beforeAll(async () => { - await factory.cleanDatabase() - const { server } = createServer({ - context: () => { + beforeAll(()=>{ + const {server} = createServer({ + context: ()=>{ return { driver, - user: authenticatedUser, + neode: instance, + user: authenticatedUser } - }, - }) - query = createTestClient(server).query - mutate = createTestClient(server).mutate + + } + } + ) + mutate = createTestClient(server).mutate + query = createTestClient(server).query }) - beforeEach(async () => { - authenticatedUser = null - - moderator = await factory.create('User', { - id: 'mod1', - role: 'moderator', - email: 'moderator@example.org', - password: '1234', - }) - user = await factory.create('User', { - id: 'user1', - role: 'user', - email: 'test@example.org', - password: '1234', - }) - author = await factory.create('User', { - id: 'auth1', - role: 'user', - name: 'abusive-user', - email: 'abusive-user@example.org', - }) - await instance.create('Category', { - id: 'cat9', - name: 'Democracy & Politics', - icon: 'university', - }) - - await Promise.all([ - factory.create('Post', { - author, - id: 'p1', - categoryIds, - content: 'Interesting Knowledge', - }), - factory.create('Post', { - author: moderator, - id: 'p2', - categoryIds, - content: 'More things to do …', - }), - factory.create('Post', { - author: user, - id: 'p3', - categoryIds, - content: 'I am at school …', - }), - ]) - await Promise.all([ - factory.create('Comment', { - author: user, - id: 'c1', - postId: 'p1', - }), - ]) - - authenticatedUser = await user.toJson() - await Promise.all([ - mutate({ - mutation: reportMutation, - variables: { - resourceId: 'p1', - reasonCategory: 'other', - reasonDescription: 'This comment is bigoted', - }, - }), - mutate({ - mutation: reportMutation, - variables: { - resourceId: 'c1', - reasonCategory: 'discrimination_etc', - reasonDescription: 'This post is bigoted', - }, - }), - mutate({ - mutation: reportMutation, - variables: { - resourceId: 'auth1', - reasonCategory: 'doxing', - reasonDescription: 'This user is harassing me with bigoted remarks', - }, - }), - ]) - authenticatedUser = null - }) - - afterEach(async () => { + afterEach(async()=>{ await factory.cleanDatabase() }) - describe('unauthenticated', () => { - it('throws authorization error', async () => { - authenticatedUser = null - expect(query({ query: reportsQuery })).resolves.toMatchObject({ - data: { reports: null }, - errors: [{ message: 'Not Authorised!' }], + describe('create report', ()=>{ + describe('unauthenticated',()=>{ + it.only('throws authorization error', async() =>{ + await expect(mutate({mutation: reportMutation, variables})).resolves.toMatchObject({ + data: {report: null}, + errors: [{message: 'Not Authorised!'}] + }) }) }) - - it('role "user" gets no reports', async () => { - authenticatedUser = await user.toJson() - expect(query({ query: reportsQuery })).resolves.toMatchObject({ - data: { reports: null }, - errors: [{ message: 'Not Authorised!' }], - }) - }) - - it('role "moderator" gets reports', async () => { - const expected = { - // to check 'orderBy: createdAt_desc' is not possible here, because 'createdAt' does not differ - reports: expect.arrayContaining([ - expect.objectContaining({ - createdAt: expect.any(String), - reasonCategory: 'doxing', - reasonDescription: 'This user is harassing me with bigoted remarks', - submitter: expect.objectContaining({ - id: 'user1', - }), - type: 'User', - user: expect.objectContaining({ - id: 'auth1', - }), - post: null, - comment: null, - }), - expect.objectContaining({ - createdAt: expect.any(String), - reasonCategory: 'other', - reasonDescription: 'This comment is bigoted', - submitter: expect.objectContaining({ - id: 'user1', - }), - type: 'Post', - user: null, - post: expect.objectContaining({ - id: 'p1', - }), - comment: null, - }), - expect.objectContaining({ - createdAt: expect.any(String), - reasonCategory: 'discrimination_etc', - reasonDescription: 'This post is bigoted', - submitter: expect.objectContaining({ - id: 'user1', - }), - type: 'Comment', - user: null, - post: null, - comment: expect.objectContaining({ - id: 'c1', - }), - }), - ]), - } - - authenticatedUser = await moderator.toJson() - const { data } = await query({ query: reportsQuery }) - expect(data).toEqual(expected) - }) }) }) + +// describe('report mutation', () => { +// let reportMutation +// let headers +// let client +// let variables +// let createPostVariables +// let user +// const categoryIds = ['cat9'] + +// const action = () => { +// reportMutation = gql` +// mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { +// report( +// resourceId: $resourceId +// reasonCategory: $reasonCategory +// reasonDescription: $reasonDescription +// ) { +// createdAt +// reasonCategory +// reasonDescription +// type +// submitter { +// email +// } +// user { +// name +// } +// post { +// title +// } +// comment { +// content +// } +// } +// } +// ` +// client = new GraphQLClient(host, { +// headers, +// }) +// return client.request(reportMutation, variables) +// } + +// beforeEach(async () => { +// variables = { +// resourceId: 'whatever', +// reasonCategory: 'other', +// reasonDescription: 'Violates code of conduct !!!', +// } +// headers = {} +// user = await factory.create('User', { +// id: 'u1', +// role: 'user', +// email: 'test@example.org', +// password: '1234', +// }) +// await factory.create('User', { +// id: 'u2', +// role: 'user', +// name: 'abusive-user', +// email: 'abusive-user@example.org', +// }) +// await instance.create('Category', { +// id: 'cat9', +// name: 'Democracy & Politics', +// icon: 'university', +// }) +// }) + +// afterEach(async () => { +// await factory.cleanDatabase() +// }) + +// describe('unauthenticated', () => { +// it('throws authorization error', async () => { +// await expect(action()).rejects.toThrow('Not Authorised') +// }) +// }) + +// describe('authenticated', () => { +// beforeEach(async () => { +// headers = await login({ +// email: 'test@example.org', +// password: '1234', +// }) +// }) + +// describe('invalid resource id', () => { +// it('returns null', async () => { +// await expect(action()).resolves.toEqual({ +// report: null, +// }) +// }) +// }) + +// describe('valid resource id', () => { +// describe('reported resource is a user', () => { +// beforeEach(async () => { +// variables = { +// ...variables, +// resourceId: 'u2', +// } +// }) + +// it('returns type "User"', async () => { +// await expect(action()).resolves.toMatchObject({ +// report: { +// type: 'User', +// }, +// }) +// }) + +// it('returns resource in user attribute', async () => { +// await expect(action()).resolves.toMatchObject({ +// report: { +// user: { +// name: 'abusive-user', +// }, +// }, +// }) +// }) + +// it('returns the submitter', async () => { +// await expect(action()).resolves.toMatchObject({ +// report: { +// submitter: { +// email: 'test@example.org', +// }, +// }, +// }) +// }) + +// it('returns a date', async () => { +// await expect(action()).resolves.toMatchObject({ +// report: { +// createdAt: expect.any(String), +// }, +// }) +// }) + +// it('returns the reason category', async () => { +// variables = { +// ...variables, +// reasonCategory: 'criminal_behavior_violation_german_law', +// } +// await expect(action()).resolves.toMatchObject({ +// report: { +// reasonCategory: 'criminal_behavior_violation_german_law', +// }, +// }) +// }) + +// it('gives an error if the reason category is not in enum "ReasonCategory"', async () => { +// variables = { +// ...variables, +// reasonCategory: 'my_category', +// } +// await expect(action()).rejects.toThrow( +// 'got invalid value "my_category"; Expected type ReasonCategory', +// ) +// }) + +// it('returns the reason description', async () => { +// variables = { +// ...variables, +// reasonDescription: 'My reason!', +// } +// await expect(action()).resolves.toMatchObject({ +// report: { +// reasonDescription: 'My reason!', +// }, +// }) +// }) + +// it('sanitize the reason description', async () => { +// variables = { +// ...variables, +// reasonDescription: 'My reason !', +// } +// await expect(action()).resolves.toMatchObject({ +// report: { +// reasonDescription: 'My reason !', +// }, +// }) +// }) +// }) + +// describe('reported resource is a post', () => { +// beforeEach(async () => { +// await factory.create('Post', { +// author: user, +// id: 'p23', +// title: 'Matt and Robert having a pair-programming', +// categoryIds, +// }) +// variables = { +// ...variables, +// resourceId: 'p23', +// } +// }) + +// it('returns type "Post"', async () => { +// await expect(action()).resolves.toMatchObject({ +// report: { +// type: 'Post', +// }, +// }) +// }) + +// it('returns resource in post attribute', async () => { +// await expect(action()).resolves.toMatchObject({ +// report: { +// post: { +// title: 'Matt and Robert having a pair-programming', +// }, +// }, +// }) +// }) + +// it('returns null in user attribute', async () => { +// await expect(action()).resolves.toMatchObject({ +// report: { +// user: null, +// }, +// }) +// }) +// }) + +// /* An der Stelle würde ich den p23 noch mal prüfen, diesmal muss aber eine error meldung kommen. +// At this point I would check the p23 again, but this time there must be an error message. */ + +// describe('reported resource is a comment', () => { +// beforeEach(async () => { +// createPostVariables = { +// id: 'p1', +// title: 'post to comment on', +// content: 'please comment on me', +// categoryIds, +// } +// await factory.create('Post', { ...createPostVariables, author: user }) +// await factory.create('Comment', { +// author: user, +// postId: 'p1', +// id: 'c34', +// content: 'Robert getting tired.', +// }) +// variables = { +// ...variables, +// resourceId: 'c34', +// } +// }) + +// it('returns type "Comment"', async () => { +// await expect(action()).resolves.toMatchObject({ +// report: { +// type: 'Comment', +// }, +// }) +// }) + +// it('returns resource in comment attribute', async () => { +// await expect(action()).resolves.toMatchObject({ +// report: { +// comment: { +// content: 'Robert getting tired.', +// }, +// }, +// }) +// }) +// }) + +// /* An der Stelle würde ich den c34 noch mal prüfen, diesmal muss aber eine error meldung kommen. +// At this point I would check the c34 again, but this time there must be an error message. */ + +// describe('reported resource is a tag', () => { +// beforeEach(async () => { +// await factory.create('Tag', { +// id: 't23', +// }) +// variables = { +// ...variables, +// resourceId: 't23', +// } +// }) + +// it('returns null', async () => { +// await expect(action()).resolves.toMatchObject({ +// report: null, +// }) +// }) +// }) + +// /* An der Stelle würde ich den t23 noch mal prüfen, diesmal muss aber eine error meldung kommen. +// At this point I would check the t23 again, but this time there must be an error message. */ +// }) +// }) +// }) + +// describe('reports query', () => { +// let query, mutate, authenticatedUser, moderator, user, author +// const categoryIds = ['cat9'] + +// const reportMutation = gql` +// mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { +// report( +// resourceId: $resourceId +// reasonCategory: $reasonCategory +// reasonDescription: $reasonDescription +// ) { +// type +// } +// } +// ` +// const reportsQuery = gql` +// query { +// reports(orderBy: createdAt_desc) { +// createdAt +// reasonCategory +// reasonDescription +// submitter { +// id +// } +// type +// user { +// id +// } +// post { +// id +// } +// comment { +// id +// } +// } +// } +// ` + +// beforeAll(async () => { +// await factory.cleanDatabase() +// const { server } = createServer({ +// context: () => { +// return { +// driver, +// user: authenticatedUser, +// } +// }, +// }) +// query = createTestClient(server).query +// mutate = createTestClient(server).mutate +// }) + +// beforeEach(async () => { +// authenticatedUser = null + +// moderator = await factory.create('User', { +// id: 'mod1', +// role: 'moderator', +// email: 'moderator@example.org', +// password: '1234', +// }) +// user = await factory.create('User', { +// id: 'user1', +// role: 'user', +// email: 'test@example.org', +// password: '1234', +// }) +// author = await factory.create('User', { +// id: 'auth1', +// role: 'user', +// name: 'abusive-user', +// email: 'abusive-user@example.org', +// }) +// await instance.create('Category', { +// id: 'cat9', +// name: 'Democracy & Politics', +// icon: 'university', +// }) + +// await Promise.all([ +// factory.create('Post', { +// author, +// id: 'p1', +// categoryIds, +// content: 'Interesting Knowledge', +// }), +// factory.create('Post', { +// author: moderator, +// id: 'p2', +// categoryIds, +// content: 'More things to do …', +// }), +// factory.create('Post', { +// author: user, +// id: 'p3', +// categoryIds, +// content: 'I am at school …', +// }), +// ]) +// await Promise.all([ +// factory.create('Comment', { +// author: user, +// id: 'c1', +// postId: 'p1', +// }), +// ]) + +// authenticatedUser = await user.toJson() +// await Promise.all([ +// mutate({ +// mutation: reportMutation, +// variables: { +// resourceId: 'p1', +// reasonCategory: 'other', +// reasonDescription: 'This comment is bigoted', +// }, +// }), +// mutate({ +// mutation: reportMutation, +// variables: { +// resourceId: 'c1', +// reasonCategory: 'discrimination_etc', +// reasonDescription: 'This post is bigoted', +// }, +// }), +// mutate({ +// mutation: reportMutation, +// variables: { +// resourceId: 'auth1', +// reasonCategory: 'doxing', +// reasonDescription: 'This user is harassing me with bigoted remarks', +// }, +// }), +// ]) +// authenticatedUser = null +// }) + +// afterEach(async () => { +// await factory.cleanDatabase() +// }) + +// describe('unauthenticated', () => { +// it('throws authorization error', async () => { +// authenticatedUser = null +// expect(query({ query: reportsQuery })).resolves.toMatchObject({ +// data: { reports: null }, +// errors: [{ message: 'Not Authorised!' }], +// }) +// }) + +// it('role "user" gets no reports', async () => { +// authenticatedUser = await user.toJson() +// expect(query({ query: reportsQuery })).resolves.toMatchObject({ +// data: { reports: null }, +// errors: [{ message: 'Not Authorised!' }], +// }) +// }) + +// it('role "moderator" gets reports', async () => { +// const expected = { +// // to check 'orderBy: createdAt_desc' is not possible here, because 'createdAt' does not differ +// reports: expect.arrayContaining([ +// expect.objectContaining({ +// createdAt: expect.any(String), +// reasonCategory: 'doxing', +// reasonDescription: 'This user is harassing me with bigoted remarks', +// submitter: expect.objectContaining({ +// id: 'user1', +// }), +// type: 'User', +// user: expect.objectContaining({ +// id: 'auth1', +// }), +// post: null, +// comment: null, +// }), +// expect.objectContaining({ +// createdAt: expect.any(String), +// reasonCategory: 'other', +// reasonDescription: 'This comment is bigoted', +// submitter: expect.objectContaining({ +// id: 'user1', +// }), +// type: 'Post', +// user: null, +// post: expect.objectContaining({ +// id: 'p1', +// }), +// comment: null, +// }), +// expect.objectContaining({ +// createdAt: expect.any(String), +// reasonCategory: 'discrimination_etc', +// reasonDescription: 'This post is bigoted', +// submitter: expect.objectContaining({ +// id: 'user1', +// }), +// type: 'Comment', +// user: null, +// post: null, +// comment: expect.objectContaining({ +// id: 'c1', +// }), +// }), +// ]), +// } + +// authenticatedUser = await moderator.toJson() +// const { data } = await query({ query: reportsQuery }) +// expect(data).toEqual(expected) +// }) +// }) +// }) From bcb880db5e4ec2bb1b23b395f7ef7052fc158ace Mon Sep 17 00:00:00 2001 From: aonomike Date: Sat, 19 Oct 2019 12:51:16 +0300 Subject: [PATCH 35/56] Start refactor of authenticated user path - Refactor report invlid resource - Start refactor of valid resource path --- backend/src/schema/resolvers/reports.spec.js | 239 ++++++++----------- 1 file changed, 96 insertions(+), 143 deletions(-) diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.js index 2c853d1fa..f247e2ec5 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.js @@ -8,66 +8,116 @@ const factory = Factory() const instance = getNeode() const driver = getDriver() -describe('report',()=>{ - let authenticatedUser, mutate, query +describe('report', () => { + let authenticatedUser, user, mutate, query const reportMutation = gql` - mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { - report( - resourceId: $resourceId - reasonCategory: $reasonCategory - reasonDescription: $reasonDescription - ) { - createdAt - reasonCategory - reasonDescription - type - submitter { - email - } - user { - name - } - post { - title - } - comment { - content + mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { + report( + resourceId: $resourceId + reasonCategory: $reasonCategory + reasonDescription: $reasonDescription + ) { + createdAt + reasonCategory + reasonDescription + type + submitter { + email + } + user { + name + } + post { + title + } + comment { + content + } } } + ` + const variables = { + resourceId: 'whatever', + reasonCategory: 'other', + reasonDescription: 'Violates code of conduct !!!', } -` -const variables = { - resourceId: 'whatever', - reasonCategory: 'other', - reasonDescription: 'Violates code of conduct !!!', -} - beforeAll(()=>{ - const {server} = createServer({ - context: ()=>{ + beforeAll(() => { + const { server } = createServer({ + context: () => { return { driver, neode: instance, - user: authenticatedUser + user: authenticatedUser, } - - } - } - ) - mutate = createTestClient(server).mutate - query = createTestClient(server).query + }, + }) + mutate = createTestClient(server).mutate + query = createTestClient(server).query }) - afterEach(async()=>{ + afterEach(async () => { await factory.cleanDatabase() }) - describe('create report', ()=>{ - describe('unauthenticated',()=>{ - it.only('throws authorization error', async() =>{ - await expect(mutate({mutation: reportMutation, variables})).resolves.toMatchObject({ - data: {report: null}, - errors: [{message: 'Not Authorised!'}] + describe('create report', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + authenticatedUser = null + await expect(mutate({ mutation: reportMutation, variables })).resolves.toMatchObject({ + data: { report: null }, + errors: [{ message: 'Not Authorised!' }], + }) + }) + }) + + describe('authenticated', () => { + const categoryIds = ['cat9'] + beforeEach(async () => { + user = await factory.create('User', { + id: 'u1', + role: 'user', + email: 'test@example.org', + password: '1234', + }) + await factory.create('User', { + id: 'abusive-user-id', + role: 'user', + name: 'abusive-user', + email: 'abusive-user@example.org', + }) + await instance.create('Category', { + id: 'cat9', + name: 'Democracy & Politics', + icon: 'university', + }) + + authenticatedUser = await user.toJson() + }) + + describe('invalid resource id', () => { + it('returns null', async () => { + await expect(mutate({ mutation: reportMutation, variables })).resolves.toMatchObject({ + data: { report: null }, + errors: undefined, + }) + }) + }) + + describe('valid resource', () => { + describe('reported resource is a user', () => { + it('returns type "User"', async () => { + await expect( + mutate({ mutation: reportMutation, variables: { ...variables, resourceId: 'abusive-user-id' } }), + ).resolves.toMatchObject({ + data: { + report: { + type: 'User', + }, + }, + errors: undefined, + }) + }) }) }) }) @@ -83,107 +133,10 @@ const variables = { // let user // const categoryIds = ['cat9'] -// const action = () => { -// reportMutation = gql` -// mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { -// report( -// resourceId: $resourceId -// reasonCategory: $reasonCategory -// reasonDescription: $reasonDescription -// ) { -// createdAt -// reasonCategory -// reasonDescription -// type -// submitter { -// email -// } -// user { -// name -// } -// post { -// title -// } -// comment { -// content -// } -// } -// } -// ` -// client = new GraphQLClient(host, { -// headers, -// }) -// return client.request(reportMutation, variables) -// } - -// beforeEach(async () => { -// variables = { -// resourceId: 'whatever', -// reasonCategory: 'other', -// reasonDescription: 'Violates code of conduct !!!', -// } -// headers = {} -// user = await factory.create('User', { -// id: 'u1', -// role: 'user', -// email: 'test@example.org', -// password: '1234', -// }) -// await factory.create('User', { -// id: 'u2', -// role: 'user', -// name: 'abusive-user', -// email: 'abusive-user@example.org', -// }) -// await instance.create('Category', { -// id: 'cat9', -// name: 'Democracy & Politics', -// icon: 'university', -// }) -// }) - -// afterEach(async () => { -// await factory.cleanDatabase() -// }) - -// describe('unauthenticated', () => { -// it('throws authorization error', async () => { -// await expect(action()).rejects.toThrow('Not Authorised') -// }) -// }) - // describe('authenticated', () => { -// beforeEach(async () => { -// headers = await login({ -// email: 'test@example.org', -// password: '1234', -// }) -// }) - -// describe('invalid resource id', () => { -// it('returns null', async () => { -// await expect(action()).resolves.toEqual({ -// report: null, -// }) -// }) -// }) // describe('valid resource id', () => { // describe('reported resource is a user', () => { -// beforeEach(async () => { -// variables = { -// ...variables, -// resourceId: 'u2', -// } -// }) - -// it('returns type "User"', async () => { -// await expect(action()).resolves.toMatchObject({ -// report: { -// type: 'User', -// }, -// }) -// }) // it('returns resource in user attribute', async () => { // await expect(action()).resolves.toMatchObject({ From 28f0431ffae99939903b2eced1b78c5de264f7b0 Mon Sep 17 00:00:00 2001 From: aonomike Date: Sat, 19 Oct 2019 13:34:54 +0300 Subject: [PATCH 36/56] Refactor tests for reporting a user --- backend/src/schema/resolvers/reports.spec.js | 211 ++++++++++++------- 1 file changed, 137 insertions(+), 74 deletions(-) diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.js index f247e2ec5..e035938c5 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.js @@ -108,7 +108,10 @@ describe('report', () => { describe('reported resource is a user', () => { it('returns type "User"', async () => { await expect( - mutate({ mutation: reportMutation, variables: { ...variables, resourceId: 'abusive-user-id' } }), + mutate({ + mutation: reportMutation, + variables: { ...variables, resourceId: 'abusive-user-id' }, + }), ).resolves.toMatchObject({ data: { report: { @@ -118,6 +121,139 @@ describe('report', () => { errors: undefined, }) }) + + it('returns resource in user attribute', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { ...variables, resourceId: 'abusive-user-id' }, + }), + ).resolves.toMatchObject({ + data: { + report: { + user: { + name: 'abusive-user', + }, + }, + }, + errors: undefined, + }) + }) + + it('returns the submitter', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { ...variables, resourceId: 'abusive-user-id' }, + }), + ).resolves.toMatchObject({ + data: { + report: { + submitter: { + email: 'test@example.org', + }, + }, + }, + errors: undefined, + }) + }) + + it('returns a date', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { ...variables, resourceId: 'abusive-user-id' }, + }), + ).resolves.toMatchObject({ + data: { + report: { + createdAt: expect.any(String), + }, + }, + errors: undefined, + }) + }) + + it('returns the reason category', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { + ...variables, + resourceId: 'abusive-user-id', + reasonCategory: 'criminal_behavior_violation_german_law', + }, + }), + ).resolves.toMatchObject({ + data: { + report: { + reasonCategory: 'criminal_behavior_violation_german_law', + }, + }, + errors: undefined, + }) + }) + + it('gives an error if the reason category is not in enum "ReasonCategory"', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { + ...variables, + resourceId: 'abusive-user-id', + reasonCategory: 'category_missing_from_enum_reason_category', + }, + }), + ).resolves.toMatchObject({ + data: undefined, + errors: [ + { + message: + 'Variable "$reasonCategory" got invalid value "category_missing_from_enum_reason_category"; Expected type ReasonCategory.', + }, + ], + }) + }) + + it('returns the reason description', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { + ...variables, + resourceId: 'abusive-user-id', + reasonDescription: 'My reason!', + }, + }), + ).resolves.toMatchObject({ + data: { + report: { + reasonDescription: 'My reason!', + }, + }, + errors: undefined, + }) + }) + + it('sanitize the reason description', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { + ...variables, + resourceId: 'abusive-user-id', + reasonDescription: 'My reason !', + }, + }), + ).resolves.toMatchObject({ + data: { + report: { + reasonDescription: 'My reason !', + }, + }, + errors: undefined, + }) + }) }) }) }) @@ -138,79 +274,6 @@ describe('report', () => { // describe('valid resource id', () => { // describe('reported resource is a user', () => { -// it('returns resource in user attribute', async () => { -// await expect(action()).resolves.toMatchObject({ -// report: { -// user: { -// name: 'abusive-user', -// }, -// }, -// }) -// }) - -// it('returns the submitter', async () => { -// await expect(action()).resolves.toMatchObject({ -// report: { -// submitter: { -// email: 'test@example.org', -// }, -// }, -// }) -// }) - -// it('returns a date', async () => { -// await expect(action()).resolves.toMatchObject({ -// report: { -// createdAt: expect.any(String), -// }, -// }) -// }) - -// it('returns the reason category', async () => { -// variables = { -// ...variables, -// reasonCategory: 'criminal_behavior_violation_german_law', -// } -// await expect(action()).resolves.toMatchObject({ -// report: { -// reasonCategory: 'criminal_behavior_violation_german_law', -// }, -// }) -// }) - -// it('gives an error if the reason category is not in enum "ReasonCategory"', async () => { -// variables = { -// ...variables, -// reasonCategory: 'my_category', -// } -// await expect(action()).rejects.toThrow( -// 'got invalid value "my_category"; Expected type ReasonCategory', -// ) -// }) - -// it('returns the reason description', async () => { -// variables = { -// ...variables, -// reasonDescription: 'My reason!', -// } -// await expect(action()).resolves.toMatchObject({ -// report: { -// reasonDescription: 'My reason!', -// }, -// }) -// }) - -// it('sanitize the reason description', async () => { -// variables = { -// ...variables, -// reasonDescription: 'My reason !', -// } -// await expect(action()).resolves.toMatchObject({ -// report: { -// reasonDescription: 'My reason !', -// }, -// }) -// }) // }) // describe('reported resource is a post', () => { From 58d1ce65155e4258aea07699f58b950d04e3f444 Mon Sep 17 00:00:00 2001 From: aonomike Date: Sat, 19 Oct 2019 14:27:51 +0300 Subject: [PATCH 37/56] Refactor tests for reporting a post --- backend/src/schema/resolvers/reports.spec.js | 119 ++++++++++++------- 1 file changed, 79 insertions(+), 40 deletions(-) diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.js index e035938c5..890908cb4 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.js @@ -9,7 +9,7 @@ const instance = getNeode() const driver = getDriver() describe('report', () => { - let authenticatedUser, user, mutate, query + let authenticatedUser, currentUser, mutate, query const reportMutation = gql` mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { report( @@ -74,8 +74,8 @@ describe('report', () => { describe('authenticated', () => { const categoryIds = ['cat9'] beforeEach(async () => { - user = await factory.create('User', { - id: 'u1', + currentUser = await factory.create('User', { + id: 'current-user-id', role: 'user', email: 'test@example.org', password: '1234', @@ -92,7 +92,7 @@ describe('report', () => { icon: 'university', }) - authenticatedUser = await user.toJson() + authenticatedUser = await currentUser.toJson() }) describe('invalid resource id', () => { @@ -255,16 +255,87 @@ describe('report', () => { }) }) }) + + describe('reported resource is a post', () => { + beforeEach(async () => { + await factory.create('Post', { + author: currentUser, + id: 'post-to-report-id', + title: 'This is a post that is going to be reported', + categoryIds, + }) + }) + + it('returns type "Post"', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { + ...variables, + resourceId: 'post-to-report-id', + }, + }), + ).resolves.toMatchObject({ + data: { + report: { + type: 'Post', + }, + }, + errors: undefined, + }) + }) + + it('returns resource in post attribute', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { + ...variables, + resourceId: 'post-to-report-id', + }, + }), + ).resolves.toMatchObject({ + data: { + report: { + post: { + title: 'This is a post that is going to be reported', + }, + }, + }, + errors: undefined, + }) + }) + + it('returns null in user attribute', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { + ...variables, + resourceId: 'post-to-report-id', + }, + }), + ).resolves.toMatchObject({ + data: { + report: { + user: null, + }, + }, + errors: undefined, + }) + }) + }) + + /* An der Stelle würde ich den p23 noch mal prüfen, diesmal muss aber eine error meldung kommen. + At this point I would check the p23 again, but this time there must be an error message. */ }) }) }) }) // describe('report mutation', () => { -// let reportMutation -// let headers + // let client -// let variables // let createPostVariables // let user // const categoryIds = ['cat9'] @@ -272,41 +343,9 @@ describe('report', () => { // describe('authenticated', () => { // describe('valid resource id', () => { -// describe('reported resource is a user', () => { - -// }) // describe('reported resource is a post', () => { -// beforeEach(async () => { -// await factory.create('Post', { -// author: user, -// id: 'p23', -// title: 'Matt and Robert having a pair-programming', -// categoryIds, -// }) -// variables = { -// ...variables, -// resourceId: 'p23', -// } -// }) - -// it('returns type "Post"', async () => { -// await expect(action()).resolves.toMatchObject({ -// report: { -// type: 'Post', -// }, -// }) -// }) - -// it('returns resource in post attribute', async () => { -// await expect(action()).resolves.toMatchObject({ -// report: { -// post: { -// title: 'Matt and Robert having a pair-programming', -// }, -// }, -// }) -// }) +// // it('returns null in user attribute', async () => { // await expect(action()).resolves.toMatchObject({ From 55abe975d9936820bfb9d8dcd0123d4e29e2685f Mon Sep 17 00:00:00 2001 From: aonomike Date: Sat, 19 Oct 2019 14:56:50 +0300 Subject: [PATCH 38/56] Refactor tests for reporting a comment --- backend/src/schema/resolvers/reports.spec.js | 124 +++++++++---------- 1 file changed, 61 insertions(+), 63 deletions(-) diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.js index 890908cb4..a2b4fc081 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.js @@ -328,79 +328,77 @@ describe('report', () => { /* An der Stelle würde ich den p23 noch mal prüfen, diesmal muss aber eine error meldung kommen. At this point I would check the p23 again, but this time there must be an error message. */ + + describe('reported resource is a comment', () => { + let createPostVariables + beforeEach(async () => { + createPostVariables = { + id: 'p1', + title: 'post to comment on', + content: 'please comment on me', + categoryIds, + } + await factory.create('Post', { ...createPostVariables, author: currentUser }) + await factory.create('Comment', { + author: currentUser, + postId: 'p1', + id: 'comment-to-report-id', + content: 'Post comment to be reported.', + }) + }) + + it('returns type "Comment"', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { + ...variables, + resourceId: 'comment-to-report-id', + }, + }), + ).resolves.toMatchObject({ + data: { + report: { + type: 'Comment', + }, + }, + errors: undefined, + }) + }) + + it('returns resource in comment attribute', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { + ...variables, + resourceId: 'comment-to-report-id', + }, + }), + ).resolves.toMatchObject({ + data: { + report: { + comment: { + content: 'Post comment to be reported.', + }, + }, + }, + errors: undefined, + }) + }) + }) + /* An der Stelle würde ich den c34 noch mal prüfen, diesmal muss aber eine error meldung kommen. + At this point I would check the c34 again, but this time there must be an error message. */ }) }) }) }) - // describe('report mutation', () => { - -// let client -// let createPostVariables -// let user -// const categoryIds = ['cat9'] - // describe('authenticated', () => { // describe('valid resource id', () => { // describe('reported resource is a post', () => { -// - -// it('returns null in user attribute', async () => { -// await expect(action()).resolves.toMatchObject({ -// report: { -// user: null, -// }, -// }) -// }) -// }) - -// /* An der Stelle würde ich den p23 noch mal prüfen, diesmal muss aber eine error meldung kommen. -// At this point I would check the p23 again, but this time there must be an error message. */ - -// describe('reported resource is a comment', () => { -// beforeEach(async () => { -// createPostVariables = { -// id: 'p1', -// title: 'post to comment on', -// content: 'please comment on me', -// categoryIds, -// } -// await factory.create('Post', { ...createPostVariables, author: user }) -// await factory.create('Comment', { -// author: user, -// postId: 'p1', -// id: 'c34', -// content: 'Robert getting tired.', -// }) -// variables = { -// ...variables, -// resourceId: 'c34', -// } -// }) - -// it('returns type "Comment"', async () => { -// await expect(action()).resolves.toMatchObject({ -// report: { -// type: 'Comment', -// }, -// }) -// }) - -// it('returns resource in comment attribute', async () => { -// await expect(action()).resolves.toMatchObject({ -// report: { -// comment: { -// content: 'Robert getting tired.', -// }, -// }, -// }) -// }) -// }) - -// /* An der Stelle würde ich den c34 noch mal prüfen, diesmal muss aber eine error meldung kommen. -// At this point I would check the c34 again, but this time there must be an error message. */ // describe('reported resource is a tag', () => { // beforeEach(async () => { From 08adff74bf8d63c4792bdf704d85d0baeaf36025 Mon Sep 17 00:00:00 2001 From: aonomike Date: Sat, 19 Oct 2019 15:08:26 +0300 Subject: [PATCH 39/56] Refactor tests for reporting a tag --- backend/src/schema/resolvers/reports.spec.js | 61 +++++++++----------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.js index a2b4fc081..1e3c4e371 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.js @@ -8,7 +8,7 @@ const factory = Factory() const instance = getNeode() const driver = getDriver() -describe('report', () => { +describe('report resources', () => { let authenticatedUser, currentUser, mutate, query const reportMutation = gql` mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { @@ -387,42 +387,37 @@ describe('report', () => { }) }) }) - /* An der Stelle würde ich den c34 noch mal prüfen, diesmal muss aber eine error meldung kommen. - At this point I would check the c34 again, but this time there must be an error message. */ + /* An der Stelle würde ich den comment-to-report-id noch mal prüfen, diesmal muss aber eine error meldung kommen. + At this point I would check the comment-to-report-id again, but this time there must be an error message. */ + describe('reported resource is a tag', () => { + beforeEach(async () => { + await factory.create('Tag', { + id: 'tag-to-report-id', + }) + }) + + it('returns null', async () => { + await expect( + mutate({ + mutation: reportMutation, + variables: { + ...variables, + resourceId: 'tag-to-report-id', + }, + }), + ).resolves.toMatchObject({ + data: { report: null }, + errors: undefined, + }) + }) + }) + + /* An der Stelle würde ich den tag-to-report-id noch mal prüfen, diesmal muss aber eine error meldung kommen. +// At this point I would check the tag-to-report-id again, but this time there must be an error message. */ }) }) }) }) -// describe('report mutation', () => { -// describe('authenticated', () => { - -// describe('valid resource id', () => { - -// describe('reported resource is a post', () => { - -// describe('reported resource is a tag', () => { -// beforeEach(async () => { -// await factory.create('Tag', { -// id: 't23', -// }) -// variables = { -// ...variables, -// resourceId: 't23', -// } -// }) - -// it('returns null', async () => { -// await expect(action()).resolves.toMatchObject({ -// report: null, -// }) -// }) -// }) - -// /* An der Stelle würde ich den t23 noch mal prüfen, diesmal muss aber eine error meldung kommen. -// At this point I would check the t23 again, but this time there must be an error message. */ -// }) -// }) -// }) // describe('reports query', () => { // let query, mutate, authenticatedUser, moderator, user, author From 4e42017afaa97fa87ec726a5bbd1605cca911375 Mon Sep 17 00:00:00 2001 From: aonomike Date: Sat, 19 Oct 2019 15:50:48 +0300 Subject: [PATCH 40/56] Refactor tests for querying reported resources --- backend/src/schema/resolvers/reports.spec.js | 401 +++++++++---------- 1 file changed, 183 insertions(+), 218 deletions(-) diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.js index 1e3c4e371..460853af8 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.js @@ -9,7 +9,8 @@ const instance = getNeode() const driver = getDriver() describe('report resources', () => { - let authenticatedUser, currentUser, mutate, query + let authenticatedUser, currentUser, mutate, query, moderator, abusiveUser + const categoryIds = ['cat9'] const reportMutation = gql` mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { report( @@ -60,7 +61,7 @@ describe('report resources', () => { await factory.cleanDatabase() }) - describe('create report', () => { + describe('report a resource', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { authenticatedUser = null @@ -72,7 +73,6 @@ describe('report resources', () => { }) describe('authenticated', () => { - const categoryIds = ['cat9'] beforeEach(async () => { currentUser = await factory.create('User', { id: 'current-user-id', @@ -413,222 +413,187 @@ describe('report resources', () => { }) /* An der Stelle würde ich den tag-to-report-id noch mal prüfen, diesmal muss aber eine error meldung kommen. -// At this point I would check the tag-to-report-id again, but this time there must be an error message. */ + At this point I would check the tag-to-report-id again, but this time there must be an error message. */ + }) + }) + }) + describe('query for reported resource', () => { + const reportsQuery = gql` + query { + reports(orderBy: createdAt_desc) { + createdAt + reasonCategory + reasonDescription + submitter { + id + } + type + user { + id + } + post { + id + } + comment { + id + } + } + } + ` + + beforeEach(async () => { + authenticatedUser = null + + moderator = await factory.create('User', { + id: 'moderator-1', + role: 'moderator', + email: 'moderator@example.org', + password: '1234', + }) + currentUser = await factory.create('User', { + id: 'current-user-id', + role: 'user', + email: 'current.user@example.org', + password: '1234', + }) + abusiveUser = await factory.create('User', { + id: 'abusive-user-1', + role: 'user', + name: 'abusive-user', + email: 'abusive-user@example.org', + }) + await instance.create('Category', { + id: 'cat9', + name: 'Democracy & Politics', + icon: 'university', + }) + + await Promise.all([ + factory.create('Post', { + author: abusiveUser, + id: 'abusive-post-1', + categoryIds, + content: 'Interesting Knowledge', + }), + factory.create('Post', { + author: moderator, + id: 'post-2', + categoryIds, + content: 'More things to do …', + }), + factory.create('Post', { + author: currentUser, + id: 'post-3', + categoryIds, + content: 'I am at school …', + }), + ]) + await Promise.all([ + factory.create('Comment', { + author: currentUser, + id: 'abusive-comment-1', + postId: 'post-1', + }), + ]) + authenticatedUser = await currentUser.toJson() + await Promise.all([ + mutate({ + mutation: reportMutation, + variables: { + resourceId: 'abusive-post-1', + reasonCategory: 'other', + reasonDescription: 'This comment is bigoted', + }, + }), + mutate({ + mutation: reportMutation, + variables: { + resourceId: 'abusive-comment-1', + reasonCategory: 'discrimination_etc', + reasonDescription: 'This post is bigoted', + }, + }), + mutate({ + mutation: reportMutation, + variables: { + resourceId: 'abusive-user-1', + reasonCategory: 'doxing', + reasonDescription: 'This user is harassing me with bigoted remarks', + }, + }), + ]) + authenticatedUser = null + }) + describe('unauthenticated', () => { + it('throws authorization error', async () => { + authenticatedUser = null + expect(query({ query: reportsQuery })).resolves.toMatchObject({ + data: { reports: null }, + errors: [{ message: 'Not Authorised!' }], + }) + }) + }) + describe('authenticated', () => { + it('role "user" gets no reports', async () => { + authenticatedUser = await currentUser.toJson() + expect(query({ query: reportsQuery })).resolves.toMatchObject({ + data: { reports: null }, + errors: [{ message: 'Not Authorised!' }], + }) + }) + + it('role "moderator" gets reports', async () => { + const expected = { + // to check 'orderBy: createdAt_desc' is not possible here, because 'createdAt' does not differ + reports: expect.arrayContaining([ + expect.objectContaining({ + createdAt: expect.any(String), + reasonCategory: 'doxing', + reasonDescription: 'This user is harassing me with bigoted remarks', + submitter: expect.objectContaining({ + id: 'current-user-id', + }), + type: 'User', + user: expect.objectContaining({ + id: 'abusive-user-1', + }), + post: null, + comment: null, + }), + expect.objectContaining({ + createdAt: expect.any(String), + reasonCategory: 'other', + reasonDescription: 'This comment is bigoted', + submitter: expect.objectContaining({ + id: 'current-user-id', + }), + type: 'Post', + user: null, + post: expect.objectContaining({ + id: 'abusive-post-1', + }), + comment: null, + }), + expect.objectContaining({ + createdAt: expect.any(String), + reasonCategory: 'discrimination_etc', + reasonDescription: 'This post is bigoted', + submitter: expect.objectContaining({ + id: 'current-user-id', + }), + type: 'Comment', + user: null, + post: null, + comment: expect.objectContaining({ + id: 'abusive-comment-1', + }), + }), + ]), + } + authenticatedUser = await moderator.toJson() + const { data } = await query({ query: reportsQuery }) + expect(data).toEqual(expected) }) }) }) }) - -// describe('reports query', () => { -// let query, mutate, authenticatedUser, moderator, user, author -// const categoryIds = ['cat9'] - -// const reportMutation = gql` -// mutation($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) { -// report( -// resourceId: $resourceId -// reasonCategory: $reasonCategory -// reasonDescription: $reasonDescription -// ) { -// type -// } -// } -// ` -// const reportsQuery = gql` -// query { -// reports(orderBy: createdAt_desc) { -// createdAt -// reasonCategory -// reasonDescription -// submitter { -// id -// } -// type -// user { -// id -// } -// post { -// id -// } -// comment { -// id -// } -// } -// } -// ` - -// beforeAll(async () => { -// await factory.cleanDatabase() -// const { server } = createServer({ -// context: () => { -// return { -// driver, -// user: authenticatedUser, -// } -// }, -// }) -// query = createTestClient(server).query -// mutate = createTestClient(server).mutate -// }) - -// beforeEach(async () => { -// authenticatedUser = null - -// moderator = await factory.create('User', { -// id: 'mod1', -// role: 'moderator', -// email: 'moderator@example.org', -// password: '1234', -// }) -// user = await factory.create('User', { -// id: 'user1', -// role: 'user', -// email: 'test@example.org', -// password: '1234', -// }) -// author = await factory.create('User', { -// id: 'auth1', -// role: 'user', -// name: 'abusive-user', -// email: 'abusive-user@example.org', -// }) -// await instance.create('Category', { -// id: 'cat9', -// name: 'Democracy & Politics', -// icon: 'university', -// }) - -// await Promise.all([ -// factory.create('Post', { -// author, -// id: 'p1', -// categoryIds, -// content: 'Interesting Knowledge', -// }), -// factory.create('Post', { -// author: moderator, -// id: 'p2', -// categoryIds, -// content: 'More things to do …', -// }), -// factory.create('Post', { -// author: user, -// id: 'p3', -// categoryIds, -// content: 'I am at school …', -// }), -// ]) -// await Promise.all([ -// factory.create('Comment', { -// author: user, -// id: 'c1', -// postId: 'p1', -// }), -// ]) - -// authenticatedUser = await user.toJson() -// await Promise.all([ -// mutate({ -// mutation: reportMutation, -// variables: { -// resourceId: 'p1', -// reasonCategory: 'other', -// reasonDescription: 'This comment is bigoted', -// }, -// }), -// mutate({ -// mutation: reportMutation, -// variables: { -// resourceId: 'c1', -// reasonCategory: 'discrimination_etc', -// reasonDescription: 'This post is bigoted', -// }, -// }), -// mutate({ -// mutation: reportMutation, -// variables: { -// resourceId: 'auth1', -// reasonCategory: 'doxing', -// reasonDescription: 'This user is harassing me with bigoted remarks', -// }, -// }), -// ]) -// authenticatedUser = null -// }) - -// afterEach(async () => { -// await factory.cleanDatabase() -// }) - -// describe('unauthenticated', () => { -// it('throws authorization error', async () => { -// authenticatedUser = null -// expect(query({ query: reportsQuery })).resolves.toMatchObject({ -// data: { reports: null }, -// errors: [{ message: 'Not Authorised!' }], -// }) -// }) - -// it('role "user" gets no reports', async () => { -// authenticatedUser = await user.toJson() -// expect(query({ query: reportsQuery })).resolves.toMatchObject({ -// data: { reports: null }, -// errors: [{ message: 'Not Authorised!' }], -// }) -// }) - -// it('role "moderator" gets reports', async () => { -// const expected = { -// // to check 'orderBy: createdAt_desc' is not possible here, because 'createdAt' does not differ -// reports: expect.arrayContaining([ -// expect.objectContaining({ -// createdAt: expect.any(String), -// reasonCategory: 'doxing', -// reasonDescription: 'This user is harassing me with bigoted remarks', -// submitter: expect.objectContaining({ -// id: 'user1', -// }), -// type: 'User', -// user: expect.objectContaining({ -// id: 'auth1', -// }), -// post: null, -// comment: null, -// }), -// expect.objectContaining({ -// createdAt: expect.any(String), -// reasonCategory: 'other', -// reasonDescription: 'This comment is bigoted', -// submitter: expect.objectContaining({ -// id: 'user1', -// }), -// type: 'Post', -// user: null, -// post: expect.objectContaining({ -// id: 'p1', -// }), -// comment: null, -// }), -// expect.objectContaining({ -// createdAt: expect.any(String), -// reasonCategory: 'discrimination_etc', -// reasonDescription: 'This post is bigoted', -// submitter: expect.objectContaining({ -// id: 'user1', -// }), -// type: 'Comment', -// user: null, -// post: null, -// comment: expect.objectContaining({ -// id: 'c1', -// }), -// }), -// ]), -// } - -// authenticatedUser = await moderator.toJson() -// const { data } = await query({ query: reportsQuery }) -// expect(data).toEqual(expected) -// }) -// }) -// }) From 8317348e583809ff70461222376bb6b53aa378c7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2019 07:39:17 +0000 Subject: [PATCH 41/56] build(deps): bump @sentry/node from 5.7.0 to 5.7.1 in /backend Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 5.7.0 to 5.7.1. - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/5.7.0...5.7.1) Signed-off-by: dependabot-preview[bot] --- backend/package.json | 2 +- backend/yarn.lock | 74 ++++++++++++++++++++++---------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/backend/package.json b/backend/package.json index f08a7d0ec..58b58314c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -42,7 +42,7 @@ }, "dependencies": { "@hapi/joi": "^16.1.7", - "@sentry/node": "^5.7.0", + "@sentry/node": "^5.7.1", "apollo-cache-inmemory": "~1.6.3", "apollo-client": "~2.6.4", "apollo-link-context": "~1.0.19", diff --git a/backend/yarn.lock b/backend/yarn.lock index 1bd66e7c9..b2d3a3775 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -1042,60 +1042,60 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= -"@sentry/core@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.7.0.tgz#c2aa5341e703ec7cf2acc69e51971a0b1f7d102a" - integrity sha512-gQel0d7LBSWJGHc7gfZllYAu+RRGD9GcYGmkRfemurmDyDGQDf/sfjiBi8f9QxUc2iFTHnvIR5nMTyf0U3yl3Q== +"@sentry/core@5.7.1": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.7.1.tgz#3eb2b7662cac68245931ee939ec809bf7a639d0e" + integrity sha512-AOn3k3uVWh2VyajcHbV9Ta4ieDIeLckfo7UMLM+CTk2kt7C89SayDGayJMSsIrsZlL4qxBoLB9QY4W2FgAGJrg== dependencies: - "@sentry/hub" "5.7.0" - "@sentry/minimal" "5.7.0" - "@sentry/types" "5.7.0" - "@sentry/utils" "5.7.0" + "@sentry/hub" "5.7.1" + "@sentry/minimal" "5.7.1" + "@sentry/types" "5.7.1" + "@sentry/utils" "5.7.1" tslib "^1.9.3" -"@sentry/hub@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.7.0.tgz#f7c356202a9db1daae82ce7f48ebf1139e4e9d02" - integrity sha512-qNdYheJ6j4P9Sk0eqIINpJohImmu/+trCwFb4F8BGLQth5iGMVQD6D0YUrgjf4ZaQwfhw9tv4W6VEfF5tyASoA== +"@sentry/hub@5.7.1": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.7.1.tgz#a52acd9fead7f3779d96e9965c6978aecc8b9cad" + integrity sha512-evGh323WR073WSBCg/RkhlUmCQyzU0xzBzCZPscvcoy5hd4SsLE6t9Zin+WACHB9JFsRQIDwNDn+D+pj3yKsig== dependencies: - "@sentry/types" "5.7.0" - "@sentry/utils" "5.7.0" + "@sentry/types" "5.7.1" + "@sentry/utils" "5.7.1" tslib "^1.9.3" -"@sentry/minimal@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.7.0.tgz#832d26bcd862c6ea628d48ad199ac7f966a2d907" - integrity sha512-0sizE2prS9nmfLyVUKmVzFFFqRNr9iorSCCejwnlRe3crqKqjf84tuRSzm6NkZjIyYj9djuuo9l9XN12NLQ/4A== +"@sentry/minimal@5.7.1": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.7.1.tgz#56afc537737586929e25349765e37a367958c1e1" + integrity sha512-nS/Dg+jWAZtcxQW8wKbkkw4dYvF6uyY/vDiz/jFCaux0LX0uhgXAC9gMOJmgJ/tYBLJ64l0ca5LzpZa7BMJQ0g== dependencies: - "@sentry/hub" "5.7.0" - "@sentry/types" "5.7.0" + "@sentry/hub" "5.7.1" + "@sentry/types" "5.7.1" tslib "^1.9.3" -"@sentry/node@^5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.7.0.tgz#153777f06b2fcd346edbff9adbb6b231c7e5fa0a" - integrity sha512-iqQbGAJDBlpQkp1rl9RkDCIfnukr4cOtHPgJPmLY19m/KXIHD2cdKhvbqoCvIPBTIAeSGQIvDT9jD5zT46eoqQ== +"@sentry/node@^5.7.1": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.7.1.tgz#94e2fbac94f6cc061be3bc14b22813536c59698d" + integrity sha512-hVM10asFStrOhYZzMqFM7V1lrHkr1ydc2n/SFG0ZmIQxfTjCVElyXV/BJASIdqadM1fFIvvtD/EfgkTcZmub1g== dependencies: - "@sentry/core" "5.7.0" - "@sentry/hub" "5.7.0" - "@sentry/types" "5.7.0" - "@sentry/utils" "5.7.0" + "@sentry/core" "5.7.1" + "@sentry/hub" "5.7.1" + "@sentry/types" "5.7.1" + "@sentry/utils" "5.7.1" cookie "^0.3.1" https-proxy-agent "^3.0.0" lru_map "^0.3.3" tslib "^1.9.3" -"@sentry/types@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.7.0.tgz#e8677e57b40c2c63cad42c02add12b238e647c10" - integrity sha512-bFRVortg713dE2yJXNFgNe6sNBVVSkpoELLkGPatdVQi0dYc6OggIIX4UZZvkynFx72GwYqO1NOrtUcJY2gmMg== +"@sentry/types@5.7.1": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.7.1.tgz#4c4c1d4d891b6b8c2c3c7b367d306a8b1350f090" + integrity sha512-tbUnTYlSliXvnou5D4C8Zr+7/wJrHLbpYX1YkLXuIJRU0NSi81bHMroAuHWILcQKWhVjaV/HZzr7Y/hhWtbXVQ== -"@sentry/utils@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.7.0.tgz#a6850aa4f5476fa26517cd5c6248f871d8d9939b" - integrity sha512-XmwQpLqea9mj8x1N7P/l4JvnEb0Rn5Py5OtBgl0ctk090W+GB1uM8rl9mkMf6698o1s1Z8T/tI/QY0yFA5uZXg== +"@sentry/utils@5.7.1": + version "5.7.1" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.7.1.tgz#cf37ad55f78e317665cd8680f202d307fa77f1d0" + integrity sha512-nhirUKj/qFLsR1i9kJ5BRvNyzdx/E2vorIsukuDrbo8e3iZ11JMgCOVrmC8Eq9YkHBqgwX4UnrPumjFyvGMZ2Q== dependencies: - "@sentry/types" "5.7.0" + "@sentry/types" "5.7.1" tslib "^1.9.3" "@sindresorhus/is@^0.14.0": From 7adeade193af74dbd41ea11e02d68c28679c5bf0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2019 07:40:38 +0000 Subject: [PATCH 42/56] build(deps-dev): bump async-validator from 3.1.0 to 3.2.0 in /webapp Bumps [async-validator](https://github.com/yiminghe/async-validator) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/yiminghe/async-validator/releases) - [Changelog](https://github.com/yiminghe/async-validator/blob/master/HISTORY.md) - [Commits](https://github.com/yiminghe/async-validator/commits/v3.2.0) Signed-off-by: dependabot-preview[bot] --- webapp/package.json | 2 +- webapp/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/webapp/package.json b/webapp/package.json index 1483ef1ee..570e78f20 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -102,7 +102,7 @@ "@vue/eslint-config-prettier": "~5.0.0", "@vue/server-test-utils": "~1.0.0-beta.29", "@vue/test-utils": "~1.0.0-beta.29", - "async-validator": "^3.1.0", + "async-validator": "^3.2.0", "babel-core": "~7.0.0-bridge.0", "babel-eslint": "~10.0.3", "babel-jest": "~24.9.0", diff --git a/webapp/yarn.lock b/webapp/yarn.lock index eb2f86951..bb5b61473 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -3832,10 +3832,10 @@ async-retry@^1.2.1: dependencies: retry "0.12.0" -async-validator@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-3.1.0.tgz#447db5eb003cbb47e650f040037a29fc3881ce92" - integrity sha512-XyAHGwtpx3Y3aHIOaGXXFo4tiulnrh+mXBU9INxig6Q8rtmtmBxDuCxb60j7EIGbAsQg9cxfJ2jrUZ+fIqEnBQ== +async-validator@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-3.2.0.tgz#fcbd644e7b5b7c9304d29a4752c3f06214ef0d56" + integrity sha512-QBuW7Qrg8wbh7Wtqw1QdN162GUmXDs9gayxFaXcCOf3bCqHJ/TQep0H4I63iVk7Q3kIGWU4wbAr/C0Uj64JiMw== async@^1.4.0: version "1.5.2" From 20e3ec19653db8115a9b42b824ffb7933f005d8e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2019 07:40:49 +0000 Subject: [PATCH 43/56] build(deps): bump faker from `10bfb9f` to `9fd8d7d` in /backend Bumps [faker](https://github.com/Marak/faker.js) from `10bfb9f` to `9fd8d7d`. - [Release notes](https://github.com/Marak/faker.js/releases) - [Commits](https://github.com/Marak/faker.js/compare/10bfb9f467b0ac2b8912ffc15690b50ef3244f09...9fd8d7d37b398842d0784a116a340f7aa6afb89b) Signed-off-by: dependabot-preview[bot] --- backend/yarn.lock | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/yarn.lock b/backend/yarn.lock index 4209e8d81..72061f949 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -3594,7 +3594,8 @@ extsprintf@^1.2.0: faker@Marak/faker.js#master: version "4.1.0" - resolved "https://codeload.github.com/Marak/faker.js/tar.gz/10bfb9f467b0ac2b8912ffc15690b50ef3244f09" + uid "9fd8d7d37b398842d0784a116a340f7aa6afb89b" + resolved "https://codeload.github.com/Marak/faker.js/tar.gz/9fd8d7d37b398842d0784a116a340f7aa6afb89b" fast-deep-equal@^2.0.1: version "2.0.1" From e3b91780c324f0e3bf9b097f652c036a48ad30be Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2019 07:41:17 +0000 Subject: [PATCH 44/56] build(deps-dev): bump date-fns from 2.5.0 to 2.5.1 Bumps [date-fns](https://github.com/date-fns/date-fns) from 2.5.0 to 2.5.1. - [Release notes](https://github.com/date-fns/date-fns/releases) - [Changelog](https://github.com/date-fns/date-fns/blob/master/CHANGELOG.md) - [Commits](https://github.com/date-fns/date-fns/compare/v2.5.0...v2.5.1) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 5387c6111..c3220c400 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "cypress-cucumber-preprocessor": "^1.16.2", "cypress-file-upload": "^3.3.4", "cypress-plugin-retries": "^1.3.0", - "date-fns": "^2.5.0", + "date-fns": "^2.5.1", "dotenv": "^8.2.0", "faker": "Marak/faker.js#master", "graphql-request": "^1.8.2", diff --git a/yarn.lock b/yarn.lock index d72b451b8..74d333ab6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1965,10 +1965,10 @@ date-fns@^1.27.2: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== -date-fns@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.5.0.tgz#b939f17c2902ce81cffe449702ba22c0781b38ec" - integrity sha512-I6Tkis01//nRcmvMQw/MRE1HAtcuA5Ie6jGPb8bJZJub7494LGOObqkV3ParnsSVviAjk5C8mNKDqYVBzCopWg== +date-fns@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.5.1.tgz#6bd76f01d3a438e9c481d4c18512ddac37585b4c" + integrity sha512-ZBrQmuaqH9YqIejbgu8f09ki7wdD2JxWsRTZ/+HnnLNmkI56ty0evnWzKY+ihLT0xX5VdUX0vDNZCxJJGKX2+Q== date-now@^0.1.4: version "0.1.4" From 8728feaa3759ccf2740dd7e9624ac9e162028f36 Mon Sep 17 00:00:00 2001 From: Mogge Date: Mon, 21 Oct 2019 11:33:26 +0200 Subject: [PATCH 45/56] fix: Only one ellipse is displayed --- webapp/plugins/vue-filters.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/webapp/plugins/vue-filters.js b/webapp/plugins/vue-filters.js index df594f5e5..399b675fa 100644 --- a/webapp/plugins/vue-filters.js +++ b/webapp/plugins/vue-filters.js @@ -31,11 +31,7 @@ export default ({ app = {} }) => { if (length <= 0) { return value } - let output = trunc(value, length).html - if (output.length < value.length) { - output += ' …' - } - return output + return trunc(value, length).html }, list: (value, glue = ', ', truncate = 0) => { if (!Array.isArray(value) || !value.length) { From 86907f2800c2893b30ab1bd0d1da628c21772e34 Mon Sep 17 00:00:00 2001 From: aonomike Date: Mon, 21 Oct 2019 13:25:56 +0300 Subject: [PATCH 46/56] Fix code review issues --- backend/src/schema/resolvers/reports.spec.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/backend/src/schema/resolvers/reports.spec.js b/backend/src/schema/resolvers/reports.spec.js index 460853af8..21b1b4a7b 100644 --- a/backend/src/schema/resolvers/reports.spec.js +++ b/backend/src/schema/resolvers/reports.spec.js @@ -43,7 +43,8 @@ describe('report resources', () => { reasonDescription: 'Violates code of conduct !!!', } - beforeAll(() => { + beforeAll(async () => { + await factory.cleanDatabase() const { server } = createServer({ context: () => { return { @@ -326,9 +327,6 @@ describe('report resources', () => { }) }) - /* An der Stelle würde ich den p23 noch mal prüfen, diesmal muss aber eine error meldung kommen. - At this point I would check the p23 again, but this time there must be an error message. */ - describe('reported resource is a comment', () => { let createPostVariables beforeEach(async () => { @@ -387,8 +385,7 @@ describe('report resources', () => { }) }) }) - /* An der Stelle würde ich den comment-to-report-id noch mal prüfen, diesmal muss aber eine error meldung kommen. - At this point I would check the comment-to-report-id again, but this time there must be an error message. */ + describe('reported resource is a tag', () => { beforeEach(async () => { await factory.create('Tag', { @@ -411,9 +408,6 @@ describe('report resources', () => { }) }) }) - - /* An der Stelle würde ich den tag-to-report-id noch mal prüfen, diesmal muss aber eine error meldung kommen. - At this point I would check the tag-to-report-id again, but this time there must be an error message. */ }) }) }) From c2c69a2f7087caa34b40a4911e59e3aef58913a4 Mon Sep 17 00:00:00 2001 From: Alina Beck Date: Mon, 21 Oct 2019 14:34:26 +0300 Subject: [PATCH 47/56] update styling and wording for pinned post ribbons --- webapp/components/PostCard/PostCard.vue | 8 ++++---- webapp/components/Ribbon/index.vue | 8 ++++++++ webapp/locales/de.json | 2 +- webapp/locales/en.json | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/webapp/components/PostCard/PostCard.vue b/webapp/components/PostCard/PostCard.vue index e1c63c121..f368fadbb 100644 --- a/webapp/components/PostCard/PostCard.vue +++ b/webapp/components/PostCard/PostCard.vue @@ -1,7 +1,7 @@