diff --git a/webapp/components/CategoriesSelect/CategoriesSelect.spec.js b/webapp/components/CategoriesSelect/CategoriesSelect.spec.js
index b633e5811..82f5e61eb 100644
--- a/webapp/components/CategoriesSelect/CategoriesSelect.spec.js
+++ b/webapp/components/CategoriesSelect/CategoriesSelect.spec.js
@@ -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')
})
diff --git a/webapp/components/CommentForm/CommentForm.spec.js b/webapp/components/CommentForm/CommentForm.spec.js
index 47bc01982..bcfea323c 100644
--- a/webapp/components/CommentForm/CommentForm.spec.js
+++ b/webapp/components/CommentForm/CommentForm.spec.js
@@ -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('.cancelBtn').trigger('submit')
expect(cancelMethodSpy).toHaveBeenCalledTimes(1)
})
diff --git a/webapp/components/ContributionForm/ContributionForm.spec.js b/webapp/components/ContributionForm/ContributionForm.spec.js
index a52169bd1..789b4e5cf 100644
--- a/webapp/components/ContributionForm/ContributionForm.spec.js
+++ b/webapp/components/ContributionForm/ContributionForm.spec.js
@@ -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"]')
diff --git a/webapp/components/DeleteData/DeleteData.spec.js b/webapp/components/DeleteData/DeleteData.spec.js
index abcdf9101..739bbe732 100644
--- a/webapp/components/DeleteData/DeleteData.spec.js
+++ b/webapp/components/DeleteData/DeleteData.spec.js
@@ -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('.ds-button-danger')
await deleteAccountBtn.trigger('click')
// second submission causes mutation to reject
diff --git a/webapp/components/MasonryGrid/MasonryGrid.spec.js b/webapp/components/MasonryGrid/MasonryGrid.spec.js
index b42b9b221..00e7859d8 100644
--- a/webapp/components/MasonryGrid/MasonryGrid.spec.js
+++ b/webapp/components/MasonryGrid/MasonryGrid.spec.js
@@ -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)
})
})
diff --git a/webapp/components/Modal.spec.js b/webapp/components/Modal.spec.js
index 2dae4285a..c309d5684 100644
--- a/webapp/components/Modal.spec.js
+++ b/webapp/components/Modal.spec.js
@@ -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)
})
})
diff --git a/webapp/components/Modal/ReportModal.spec.js b/webapp/components/Modal/ReportModal.spec.js
index b151f3c7b..de95cce99 100644
--- a/webapp/components/Modal/ReportModal.spec.js
+++ b/webapp/components/Modal/ReportModal.spec.js
@@ -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', () => {
diff --git a/webapp/components/TeaserImage/TeaserImage.vue b/webapp/components/TeaserImage/TeaserImage.vue
index a08b9e0ef..c2bf56459 100644
--- a/webapp/components/TeaserImage/TeaserImage.vue
+++ b/webapp/components/TeaserImage/TeaserImage.vue
@@ -62,14 +62,6 @@ export default {
showCropper: false,
}
},
- watch: {
- error() {
- const that = this
- setTimeout(function() {
- that.error = false
- }, 2000)
- },
- },
methods: {
template() {
return `
@@ -82,6 +74,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
diff --git a/webapp/components/Upload/spec.js b/webapp/components/Upload/spec.js
index d9878ea2d..e60429974 100644
--- a/webapp/components/Upload/spec.js
+++ b/webapp/components/Upload/spec.js
@@ -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)
diff --git a/webapp/components/generic/SearchableInput/SearchableInput.spec.js b/webapp/components/generic/SearchableInput/SearchableInput.spec.js
index db314630f..0ebcda63f 100644
--- a/webapp/components/generic/SearchableInput/SearchableInput.spec.js
+++ b/webapp/components/generic/SearchableInput/SearchableInput.spec.js
@@ -45,14 +45,16 @@ describe('SearchableInput.vue', () => {
expect(wrapper.find('.is-open').exists()).toBe(true)
})
- it('opens the select dropdown and blurs after focused on', () => {
+ it('opens the select dropdown and blurs after focused on', async () => {
select.trigger('blur')
+ await Vue.nextTick()
expect(wrapper.find('.is-open').exists()).toBe(false)
})
- it('is clearable', () => {
+ it('is clearable', async () => {
select.trigger('input')
select.trigger('keyup.esc')
+ await Vue.nextTick()
expect(wrapper.find('.is-open').exists()).toBe(false)
})
@@ -88,11 +90,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' },
})
})
@@ -102,11 +103,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' },
})
})
})
diff --git a/webapp/package.json b/webapp/package.json
index 1e56f3201..2928fe343 100644
--- a/webapp/package.json
+++ b/webapp/package.json
@@ -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",
diff --git a/webapp/pages/settings/my-social-media.spec.js b/webapp/pages/settings/my-social-media.spec.js
index b1c9e0649..dd3c1c2c3 100644
--- a/webapp/pages/settings/my-social-media.spec.js
+++ b/webapp/pages/settings/my-social-media.spec.js
@@ -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('a[name="edit"]')
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('a[name="delete"]')
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)
})
})
diff --git a/webapp/yarn.lock b/webapp/yarn.lock
index 38208d897..20dbb098c 100644
--- a/webapp/yarn.lock
+++ b/webapp/yarn.lock
@@ -2861,13 +2861,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"
@@ -5577,6 +5578,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"
@@ -9255,6 +9265,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"
@@ -9747,6 +9762,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"
@@ -12720,6 +12746,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"
@@ -14064,6 +14099,11 @@ serve-static@1.14.1, serve-static@^1.14.1:
version "1.14.1"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
+ dependencies:
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ parseurl "~1.3.3"
+ send "0.17.1"
server-destroy@^1.0.1:
version "1.0.1"