Merge remote-tracking branch 'origin/master' into 279-blacklist-users-content

This commit is contained in:
roschaefer 2020-01-16 19:48:16 +01:00
commit c5a6919833
16 changed files with 123 additions and 77 deletions

View File

@ -76,8 +76,8 @@
"metascraper-soundcloud": "^5.9.5",
"metascraper-title": "^5.10.3",
"metascraper-url": "^5.10.3",
"metascraper-video": "^5.9.5",
"metascraper-youtube": "^5.9.5",
"metascraper-video": "^5.10.3",
"metascraper-youtube": "^5.10.3",
"minimatch": "^3.0.4",
"mustache": "^3.2.1",
"neo4j-driver": "^4.0.1",

View File

@ -6057,20 +6057,20 @@ metascraper-url@^5.10.3:
dependencies:
"@metascraper/helpers" "^5.10.3"
metascraper-video@^5.9.5:
version "5.9.5"
resolved "https://registry.yarnpkg.com/metascraper-video/-/metascraper-video-5.9.5.tgz#707eb9726a96a64ecd8f234a7716c021ccf10f3f"
integrity sha512-ApYCnVpEPy3+sLHxjMVXUVolHgdEOwpaiH41win4h5HmDX6jz/gWg3ENaHWfRLTn94Gc3c2Fjkqg/dwShRK0/A==
metascraper-video@^5.10.3:
version "5.10.3"
resolved "https://registry.yarnpkg.com/metascraper-video/-/metascraper-video-5.10.3.tgz#deb0510b247aff0c9f1777a9d790f0aa55fa2890"
integrity sha512-xXGtPWX1RYSEOkLDvIzD20+o4hrSYycN31briMwQkjL7ZcuSfGgILDOCXSnT+WcpEbRNNxAOmODvAxU5qGnqjQ==
dependencies:
"@metascraper/helpers" "^5.9.5"
"@metascraper/helpers" "^5.10.3"
lodash "~4.17.15"
metascraper-youtube@^5.9.5:
version "5.9.5"
resolved "https://registry.yarnpkg.com/metascraper-youtube/-/metascraper-youtube-5.9.5.tgz#0d67c3619cfaf5434fe51bd3d18be6a6f1b31c7f"
integrity sha512-xC6e6l08/qdqNp7rtyMWPumIh0tCqNhWJkL8F5BjMZCGA3iL2OYh82v26qH/H4GdMZlxSsglNJQTjl8ywcdEmw==
metascraper-youtube@^5.10.3:
version "5.10.3"
resolved "https://registry.yarnpkg.com/metascraper-youtube/-/metascraper-youtube-5.10.3.tgz#58a121ae9b7aa8f244cbbfde66b57884390b9d64"
integrity sha512-mK+pPu3XJt6RqdoUKlXvlO9Lj2Tf+cfZwqCL1zLi8piYIyjbXDEx8VAb5Yz+GxDR57UWeFugnMtn/CpSbSDMNg==
dependencies:
"@metascraper/helpers" "^5.9.5"
"@metascraper/helpers" "^5.10.3"
get-video-id "~3.1.4"
is-reachable "~4.0.0"
p-locate "~4.1.0"

View File

@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils'
import CategoriesSelect from './CategoriesSelect'
import Vue from 'vue'
const localVue = global.localVue
@ -55,8 +56,9 @@ describe('CategoriesSelect.vue', () => {
})
describe('toggleCategory', () => {
beforeEach(() => {
beforeEach(async () => {
wrapper.vm.categories = categories
await Vue.nextTick()
democracyAndPolitics = wrapper.findAll('button').at(0)
democracyAndPolitics.trigger('click')
})

View File

@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils'
import CommentForm from './CommentForm'
import Vue from 'vue'
import MutationObserver from 'mutation-observer'
global.MutationObserver = MutationObserver
@ -74,6 +74,7 @@ describe('CommentForm.vue', () => {
it('calls `clear` method when the cancel button is clicked', async () => {
wrapper.vm.updateEditorContent('ok')
await Vue.nextTick()
await wrapper.find('[data-test="cancel-button"]').trigger('submit')
expect(cancelMethodSpy).toHaveBeenCalledTimes(1)
})

View File

@ -1,6 +1,7 @@
import { config, mount } from '@vue/test-utils'
import ContributionForm from './ContributionForm.vue'
import Vue from 'vue'
import Vuex from 'vuex'
import PostMutations from '~/graphql/PostMutations.js'
import CategoriesSelect from '~/components/CategoriesSelect/CategoriesSelect'
@ -147,31 +148,31 @@ describe('ContributionForm.vue', () => {
dataPrivacyButton.trigger('click')
})
it('title should not be empty', async () => {
it('title cannot be empty', async () => {
postTitleInput.setValue('')
wrapper.find('form').trigger('submit')
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
})
it('title should not be too long', async () => {
it('title cannot be too long', async () => {
postTitleInput.setValue(postTitleTooLong)
wrapper.find('form').trigger('submit')
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
})
it('title should not be too short', async () => {
it('title cannot be too short', async () => {
postTitleInput.setValue(postTitleTooShort)
wrapper.find('form').trigger('submit')
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
})
it('content should not be empty', async () => {
it('content cannot be empty', async () => {
await wrapper.vm.updateEditorContent('')
await wrapper.find('form').trigger('submit')
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
})
it('should have at least one category', async () => {
it('has at least one category', async () => {
dataPrivacyButton = await wrapper
.find(CategoriesSelect)
.find('[data-test="category-buttons-cat12"]')
@ -180,8 +181,9 @@ describe('ContributionForm.vue', () => {
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
})
it('should have not have more than three categories', async () => {
it('has no more than three categories', async () => {
wrapper.vm.form.categoryIds = ['cat4', 'cat9', 'cat15', 'cat27']
await Vue.nextTick()
wrapper.find('form').trigger('submit')
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
})
@ -209,10 +211,12 @@ describe('ContributionForm.vue', () => {
wrapper.find(CategoriesSelect).setData({ categories })
englishLanguage = wrapper.findAll('li').filter(language => language.text() === 'English')
englishLanguage.trigger('click')
await Vue.nextTick()
dataPrivacyButton = await wrapper
.find(CategoriesSelect)
.find('[data-test="category-buttons-cat12"]')
dataPrivacyButton.trigger('click')
await Vue.nextTick()
})
it('creates a post with valid title, content, and at least one category', async () => {
@ -278,10 +282,12 @@ describe('ContributionForm.vue', () => {
wrapper.find(CategoriesSelect).setData({ categories })
englishLanguage = wrapper.findAll('li').filter(language => language.text() === 'English')
englishLanguage.trigger('click')
await Vue.nextTick()
dataPrivacyButton = await wrapper
.find(CategoriesSelect)
.find('[data-test="category-buttons-cat12"]')
dataPrivacyButton.trigger('click')
await Vue.nextTick()
})
it('shows an error toaster when apollo mutation rejects', async () => {
@ -370,6 +376,7 @@ describe('ContributionForm.vue', () => {
it('supports updating categories', async () => {
expectedParams.variables.categoryIds.push('cat3')
wrapper.find(CategoriesSelect).setData({ categories })
await Vue.nextTick()
const healthWellbeingButton = await wrapper
.find(CategoriesSelect)
.find('[data-test="category-buttons-cat3"]')

View File

@ -1,6 +1,6 @@
import { mount } from '@vue/test-utils'
import DeleteData from './DeleteData.vue'
import Vue from 'vue'
import Vuex from 'vuex'
const localVue = global.localVue
@ -168,6 +168,7 @@ describe('DeleteData.vue', () => {
it('shows an error toaster when the mutation rejects', async () => {
enableDeletionInput = wrapper.find('.enable-deletion-input input')
enableDeletionInput.setValue(deleteAccountName)
await Vue.nextTick()
deleteAccountBtn = wrapper.find('[data-test="delete-button"]')
await deleteAccountBtn.trigger('click')
// second submission causes mutation to reject

View File

@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils'
import Vue from 'vue'
import MasonryGrid from './MasonryGrid'
const localVue = global.localVue
@ -13,29 +13,29 @@ describe('MasonryGrid', () => {
masonryGridItem = wrapper.vm.$children[0]
})
it('adds the "reset-grid-height" class when itemsCalculating is more than 0', () => {
it('adds the "reset-grid-height" class when itemsCalculating is more than 0', async () => {
wrapper.setData({ itemsCalculating: 1 })
await Vue.nextTick()
expect(wrapper.classes()).toContain('reset-grid-height')
})
it('removes the "reset-grid-height" class when itemsCalculating is 0', () => {
it('removes the "reset-grid-height" class when itemsCalculating is 0', async () => {
wrapper.setData({ itemsCalculating: 0 })
await Vue.nextTick()
expect(wrapper.classes()).not.toContain('reset-grid-height')
})
it('adds 1 to itemsCalculating when a child emits "calculating-item-height"', () => {
it('adds 1 to itemsCalculating when a child emits "calculating-item-height"', async () => {
wrapper.setData({ itemsCalculating: 0 })
masonryGridItem.$emit('calculating-item-height')
await Vue.nextTick()
expect(wrapper.vm.itemsCalculating).toBe(1)
})
it('subtracts 1 from itemsCalculating when a child emits "finished-calculating-item-height"', () => {
it('subtracts 1 from itemsCalculating when a child emits "finished-calculating-item-height"', async () => {
wrapper.setData({ itemsCalculating: 2 })
masonryGridItem.$emit('finished-calculating-item-height')
await Vue.nextTick()
expect(wrapper.vm.itemsCalculating).toBe(1)
})
})

View File

@ -5,6 +5,7 @@ import DisableModal from './Modal/DisableModal.vue'
import ReportModal from './Modal/ReportModal.vue'
import Vuex from 'vuex'
import { getters, mutations } from '../store/modal'
import Vue from 'vue'
const localVue = global.localVue
@ -89,8 +90,9 @@ describe('Modal.vue', () => {
})
describe('child component emits close', () => {
it('turns empty', () => {
it('turns empty', async () => {
wrapper.find(DisableModal).vm.$emit('close')
await Vue.nextTick()
expect(wrapper.contains(DisableModal)).toBe(false)
})
})

View File

@ -1,5 +1,6 @@
import { config, shallowMount, mount } from '@vue/test-utils'
import ReportModal from './ReportModal.vue'
import Vue from 'vue'
const localVue = global.localVue
@ -151,9 +152,11 @@ describe('ReportModal.vue', () => {
})
describe('click confirm button', () => {
beforeEach(() => {
beforeEach(async () => {
wrapper.find('.ds-radio-option-label').trigger('click')
await Vue.nextTick()
wrapper.find('button.confirm').trigger('click')
await Vue.nextTick()
})
it('calls report mutation', () => {

View File

@ -1,8 +1,8 @@
import { config, mount } from '@vue/test-utils'
import Vue from 'vue'
import { VERSION } from '~/constants/terms-and-conditions-version.js'
import CreateUserAccount from './CreateUserAccount'
import { SignupVerificationMutation } from '~/graphql/Registration.js'
const localVue = global.localVue
config.stubs['sweetalert-icon'] = '<span><slot /></span>'
@ -110,6 +110,7 @@ describe('CreateUserAccount', () => {
it('displays success', async () => {
await action()
await Vue.nextTick()
expect(mocks.$t).toHaveBeenCalledWith(
'components.registration.create-user-account.success',
)
@ -140,6 +141,7 @@ describe('CreateUserAccount', () => {
it('displays form errors', async () => {
await action()
await Vue.nextTick()
expect(mocks.$t).toHaveBeenCalledWith(
'components.registration.create-user-account.error',
)

View File

@ -70,14 +70,6 @@ export default {
showCropper: false,
}
},
watch: {
error() {
const that = this
setTimeout(function() {
that.error = false
}, 2000)
},
},
methods: {
template() {
return `<div class="dz-preview dz-file-preview">
@ -90,6 +82,9 @@ export default {
verror(file, message) {
this.error = true
this.$toast.error(file.status, message)
setTimeout(() => {
this.error = false
}, 2000)
},
transformImage(file) {
this.file = file

View File

@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils'
import Vue from 'vue'
import Upload from '.'
const localVue = global.localVue
@ -57,8 +58,9 @@ describe('Upload', () => {
expect(mocks.$toast.error).toHaveBeenCalledWith(fileError.status, message)
})
it('changes error status from false to true to false', () => {
it('changes error status from false to true to false', async () => {
wrapper.vm.verror(fileError, message)
await Vue.nextTick()
expect(wrapper.vm.error).toEqual(true)
jest.runAllTimers()
expect(wrapper.vm.error).toEqual(false)

View File

@ -87,11 +87,10 @@ describe('SearchableInput.vue', () => {
select.trigger('input')
const post = wrapper.find('.search-post')
post.trigger('click')
await Vue.nextTick().then(() => {
expect(mocks.$router.push).toHaveBeenCalledWith({
name: 'post-id-slug',
params: { id: 'post-by-jenny', slug: 'user-post-by-jenny' },
})
await Vue.nextTick()
expect(mocks.$router.push).toHaveBeenCalledWith({
name: 'post-id-slug',
params: { id: 'post-by-jenny', slug: 'user-post-by-jenny' },
})
})
@ -101,11 +100,10 @@ describe('SearchableInput.vue', () => {
const users = wrapper.findAll('.userinfo')
const bob = users.filter(item => item.text() === '@bob-der-baumeister')
bob.trigger('click')
await Vue.nextTick().then(() => {
expect(mocks.$router.push).toHaveBeenCalledWith({
name: 'profile-id-slug',
params: { id: 'u2', slug: 'bob-der-baumeister' },
})
await Vue.nextTick()
expect(mocks.$router.push).toHaveBeenCalledWith({
name: 'profile-id-slug',
params: { id: 'u2', slug: 'bob-der-baumeister' },
})
})
})

View File

@ -106,7 +106,7 @@
"@vue/cli-shared-utils": "~4.1.2",
"@vue/eslint-config-prettier": "~6.0.0",
"@vue/server-test-utils": "~1.0.0-beta.30",
"@vue/test-utils": "~1.0.0-beta.29",
"@vue/test-utils": "~1.0.0-beta.30",
"async-validator": "^3.2.3",
"babel-core": "~7.0.0-bridge.0",
"babel-eslint": "~10.0.3",

View File

@ -2,6 +2,7 @@ import { mount } from '@vue/test-utils'
import flushPromises from 'flush-promises'
import MySocialMedia from './my-social-media.vue'
import Vuex from 'vuex'
import Vue from 'vue'
const localVue = global.localVue
@ -48,10 +49,10 @@ describe('my-social-media.vue', () => {
submitButton = wrapper.find('button')
})
it('requires the link to be a valid url', () => {
it('requires the link to be a valid url', async () => {
input.setValue('some value')
form.trigger('submit')
await Vue.nextTick()
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
})
@ -59,19 +60,19 @@ describe('my-social-media.vue', () => {
mocks.$apollo.mutate.mockRejectedValue({ message: 'Ouch!' })
input.setValue(newSocialMediaUrl)
form.trigger('submit')
await Vue.nextTick()
await flushPromises()
expect(mocks.$toast.error).toHaveBeenCalledTimes(1)
})
describe('success', () => {
beforeEach(() => {
beforeEach(async () => {
mocks.$apollo.mutate.mockResolvedValue({
data: { CreateSocialMedia: { id: 's2', url: newSocialMediaUrl } },
})
input.setValue(newSocialMediaUrl)
form.trigger('submit')
await Vue.nextTick()
})
it('sends the new url to the backend', () => {
@ -84,13 +85,11 @@ describe('my-social-media.vue', () => {
it('displays a success message', async () => {
await flushPromises()
expect(mocks.$toast.success).toHaveBeenCalledTimes(1)
})
it('clears the form', async () => {
await flushPromises()
expect(input.value).toBe(undefined)
expect(submitButton.vm.$attrs.disabled).toBe(true)
})
@ -127,19 +126,18 @@ describe('my-social-media.vue', () => {
})
})
it('does not accept a duplicate url', () => {
input = wrapper.find('input#addSocialMedia')
input.setValue(socialMediaUrl)
it('does not accept a duplicate url', async () => {
wrapper.find('input#addSocialMedia').setValue(socialMediaUrl)
form.trigger('submit')
await Vue.nextTick()
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
})
describe('editing social media link', () => {
beforeEach(() => {
beforeEach(async () => {
const editButton = wrapper.find('.base-button[data-test="edit-button"]')
editButton.trigger('click')
await Vue.nextTick()
input = wrapper.find('input#editSocialMedia')
})
@ -149,28 +147,29 @@ describe('my-social-media.vue', () => {
expect(addInput.exists()).toBe(false)
})
it('sends the new url to the backend', () => {
it('sends the new url to the backend', async () => {
const expected = expect.objectContaining({
variables: { id: 's1', url: newSocialMediaUrl },
})
input.setValue(newSocialMediaUrl)
form.trigger('submit')
await Vue.nextTick()
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected)
})
it('allows the user to cancel editing', () => {
it('allows the user to cancel editing', async () => {
const cancelButton = wrapper.find('button#cancel')
cancelButton.trigger('click')
await Vue.nextTick()
expect(wrapper.find('input#editSocialMedia').exists()).toBe(false)
})
})
describe('deleting social media link', () => {
beforeEach(() => {
beforeEach(async () => {
const deleteButton = wrapper.find('.base-button[data-test="delete-button"]')
deleteButton.trigger('click')
await Vue.nextTick()
})
it('sends the link id to the backend', () => {
@ -184,7 +183,6 @@ describe('my-social-media.vue', () => {
it('displays a success message', async () => {
await flushPromises()
expect(mocks.$toast.success).toHaveBeenCalledTimes(1)
})
})

View File

@ -3159,13 +3159,14 @@
"@types/cheerio" "^0.22.10"
cheerio "^1.0.0-rc.2"
"@vue/test-utils@~1.0.0-beta.29":
version "1.0.0-beta.29"
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.29.tgz#c942cf25e891cf081b6a03332b4ae1ef430726f0"
integrity sha512-yX4sxEIHh4M9yAbLA/ikpEnGKMNBCnoX98xE1RwxfhQVcn0MaXNSj1Qmac+ZydTj6VBSEVukchBogXBTwc+9iA==
"@vue/test-utils@~1.0.0-beta.30":
version "1.0.0-beta.30"
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.30.tgz#d5f26d1e2411fdb7fa7fdedb61b4b4ea4194c49d"
integrity sha512-Wyvcha9fNk8+kzTDwb3xWGjPkCPzHSYSwKP6MplrPTG/auhqoad7JqUEceZLc6u7AU4km2pPQ8/m9s0RgCZ0NA==
dependencies:
dom-event-types "^1.0.0"
lodash "^4.17.4"
lodash "^4.17.15"
pretty "^2.0.0"
"@webassemblyjs/ast@1.8.5":
version "1.8.5"
@ -5917,6 +5918,15 @@ concat-stream@^1.5.0:
readable-stream "^2.2.2"
typedarray "^0.0.6"
condense-newlines@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/condense-newlines/-/condense-newlines-0.2.1.tgz#3de985553139475d32502c83b02f60684d24c55f"
integrity sha1-PemFVTE5R10yUCyDsC9gaE0kxV8=
dependencies:
extend-shallow "^2.0.1"
is-whitespace "^0.3.0"
kind-of "^3.0.2"
config-chain@^1.1.12:
version "1.1.12"
resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
@ -9802,6 +9812,11 @@ is-utf8@^0.2.0:
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
is-whitespace@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f"
integrity sha1-Fjnssb4DauxppUy7QBz77XEUq38=
is-window@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-window/-/is-window-1.0.2.tgz#2c896ca53db97de45d3c33133a65d8c9f563480d"
@ -10304,6 +10319,17 @@ js-base64@^2.1.8:
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121"
integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==
js-beautify@^1.6.12:
version "1.10.2"
resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.2.tgz#88c9099cd6559402b124cfab18754936f8a7b178"
integrity sha512-ZtBYyNUYJIsBWERnQP0rPN9KjkrDfJcMjuVGcvXOUJrD1zmOGwhRwQ4msG+HJ+Ni/FA7+sRQEMYVzdTQDvnzvQ==
dependencies:
config-chain "^1.1.12"
editorconfig "^0.15.3"
glob "^7.1.3"
mkdirp "~0.5.1"
nopt "~4.0.1"
js-beautify@^1.6.14:
version "1.10.0"
resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.0.tgz#9753a13c858d96828658cd18ae3ca0e5783ea672"
@ -13369,6 +13395,15 @@ pretty-time@^1.1.0:
resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e"
integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==
pretty@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pretty/-/pretty-2.0.0.tgz#adbc7960b7bbfe289a557dc5f737619a220d06a5"
integrity sha1-rbx5YLe7/iiaVX3F9zdhmiINBqU=
dependencies:
condense-newlines "^0.2.1"
extend-shallow "^2.0.1"
js-beautify "^1.6.12"
prismjs@^1.8.4, prismjs@~1.17.0:
version "1.17.1"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.17.1.tgz#e669fcbd4cdd873c35102881c33b14d0d68519be"