mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Merge remote-tracking branch 'origin/master' into 206_setup_neo4j_db_constraints_on_startup
This commit is contained in:
commit
3952578ffb
@ -11,7 +11,7 @@
|
||||
"lint": "eslint src --config .eslintrc.js",
|
||||
"test": "run-s test:jest test:cucumber",
|
||||
"test:before:server": "cross-env GRAPHQL_URI=http://localhost:4123 GRAPHQL_PORT=4123 yarn run dev 2> /dev/null",
|
||||
"test:before:seeder": "cross-env GRAPHQL_URI=http://localhost:4001 GRAPHQL_PORT=4001 DEBUG=true DISABLED_MIDDLEWARES=permissions,activityPub yarn run dev 2> /dev/null",
|
||||
"test:before:seeder": "cross-env GRAPHQL_URI=http://localhost:4001 GRAPHQL_PORT=4001 DISABLED_MIDDLEWARES=permissions,activityPub yarn run dev 2> /dev/null",
|
||||
"test:jest:cmd": "wait-on tcp:4001 tcp:4123 && jest --forceExit --detectOpenHandles --runInBand",
|
||||
"test:cucumber:cmd": "wait-on tcp:4001 tcp:4123 && cucumber-js --require-module @babel/register --exit test/",
|
||||
"test:jest:cmd:debug": "wait-on tcp:4001 tcp:4123 && node --inspect-brk ./node_modules/.bin/jest -i --forceExit --detectOpenHandles --runInBand",
|
||||
@ -19,8 +19,8 @@
|
||||
"test:cucumber": " cross-env CLIENT_URI=http://localhost:4123 run-p --race test:before:* 'test:cucumber:cmd {@}' --",
|
||||
"test:jest:debug": "run-p --race test:before:* 'test:jest:cmd:debug {@}' --",
|
||||
"db:script:seed": "wait-on tcp:4001 && babel-node src/seed/seed-db.js",
|
||||
"db:reset": "cross-env DEBUG=true babel-node src/seed/reset-db.js",
|
||||
"db:seed": "cross-env GRAPHQL_URI=http://localhost:4001 GRAPHQL_PORT=4001 DEBUG=true DISABLED_MIDDLEWARES=permissions run-p --race dev db:script:seed"
|
||||
"db:reset": "cross-env babel-node src/seed/reset-db.js",
|
||||
"db:seed": "cross-env GRAPHQL_URI=http://localhost:4001 GRAPHQL_PORT=4001 DISABLED_MIDDLEWARES=permissions run-p --race dev db:script:seed"
|
||||
},
|
||||
"author": "Human Connection gGmbH",
|
||||
"license": "MIT",
|
||||
@ -109,4 +109,4 @@
|
||||
"prettier": "~1.17.1",
|
||||
"supertest": "~4.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,8 @@ export const serverConfigs = {
|
||||
export const developmentConfigs = {
|
||||
DEBUG: process.env.NODE_ENV !== 'production' && process.env.DEBUG === 'true',
|
||||
MOCKS: process.env.MOCKS === 'true',
|
||||
DISABLED_MIDDLEWARES: process.env.DISABLED_MIDDLEWARES || '',
|
||||
DISABLED_MIDDLEWARES:
|
||||
(process.env.NODE_ENV !== 'production' && process.env.DISABLED_MIDDLEWARES) || '',
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@ -50,7 +50,7 @@ export default schema => {
|
||||
]
|
||||
|
||||
// add permisions middleware at the first position (unless we're seeding)
|
||||
if (CONFIG.DEBUG) {
|
||||
if (CONFIG.DISABLED_MIDDLEWARES) {
|
||||
const disabledMiddlewares = CONFIG.DISABLED_MIDDLEWARES.split(',')
|
||||
order = order.filter(key => {
|
||||
return !disabledMiddlewares.includes(key)
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { cleanDatabase } from './factories'
|
||||
import CONFIG from './../config'
|
||||
|
||||
if (!CONFIG.DEBUG) {
|
||||
throw new Error(`YOU CAN'T CLEAN THE DATABASE WITH DEBUG=${CONFIG.DEBUG}`)
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
throw new Error(`You cannot clean the database in production environment!`)
|
||||
}
|
||||
|
||||
;(async function() {
|
||||
|
||||
@ -1,25 +1,28 @@
|
||||
import { When, Then } from 'cypress-cucumber-preprocessor/steps'
|
||||
import { When, Then } from "cypress-cucumber-preprocessor/steps";
|
||||
|
||||
const narratorAvatar = 'https://s3.amazonaws.com/uifaces/faces/twitter/nerrsoft/128.jpg'
|
||||
const narratorAvatar =
|
||||
"https://s3.amazonaws.com/uifaces/faces/twitter/nerrsoft/128.jpg";
|
||||
|
||||
Then('I click on the {string} button', text => {
|
||||
cy.get('button').contains(text).click()
|
||||
})
|
||||
Then("I click on the {string} button", text => {
|
||||
cy.get("button")
|
||||
.contains(text)
|
||||
.click();
|
||||
});
|
||||
|
||||
Then('my comment should be successfully created', () => {
|
||||
cy.get('.iziToast-message')
|
||||
.contains('Comment Submitted')
|
||||
})
|
||||
Then("my comment should be successfully created", () => {
|
||||
cy.get(".iziToast-message").contains("Comment Submitted");
|
||||
});
|
||||
|
||||
Then('I should see my comment', () => {
|
||||
cy.get('div.comment p')
|
||||
.should('contain', 'Human Connection rocks')
|
||||
.get('.ds-avatar img')
|
||||
.should('have.attr', 'src')
|
||||
.and('contain', narratorAvatar)
|
||||
})
|
||||
Then("I should see my comment", () => {
|
||||
cy.get("div.comment p")
|
||||
.should("contain", "Human Connection rocks")
|
||||
.get(".ds-avatar img")
|
||||
.should("have.attr", "src")
|
||||
.and("contain", narratorAvatar)
|
||||
.get("div p.ds-text span")
|
||||
.should("contain", "today at");
|
||||
});
|
||||
|
||||
Then('the editor should be cleared', () => {
|
||||
cy.get('.ProseMirror p')
|
||||
.should('have.class', 'is-empty')
|
||||
})
|
||||
Then("the editor should be cleared", () => {
|
||||
cy.get(".ProseMirror p").should("have.class", "is-empty");
|
||||
});
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
</div>
|
||||
<div v-else :class="{ comment: true, 'disabled-content': comment.deleted || comment.disabled }">
|
||||
<ds-space margin-bottom="x-small">
|
||||
<hc-user :user="author" />
|
||||
<hc-user :user="author" :date-time="comment.createdAt" />
|
||||
</ds-space>
|
||||
<no-ssr>
|
||||
<content-menu
|
||||
@ -45,6 +45,7 @@ export default {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
dateTime: { type: [Date, String], default: null },
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
|
||||
@ -98,13 +98,23 @@ export default {
|
||||
}
|
||||
|
||||
if (!this.isOwner && this.isModerator) {
|
||||
routes.push({
|
||||
name: this.$t(`disable.${this.resourceType}.title`),
|
||||
callback: () => {
|
||||
this.openModal('disable')
|
||||
},
|
||||
icon: 'eye-slash',
|
||||
})
|
||||
if (!this.resource.disabled) {
|
||||
routes.push({
|
||||
name: this.$t(`disable.${this.resourceType}.title`),
|
||||
callback: () => {
|
||||
this.openModal('disable')
|
||||
},
|
||||
icon: 'eye-slash',
|
||||
})
|
||||
} else {
|
||||
routes.push({
|
||||
name: this.$t(`release.${this.resourceType}.title`),
|
||||
callback: () => {
|
||||
this.openModal('release', this.resource.id)
|
||||
},
|
||||
icon: 'eye',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isOwner && this.resourceType === 'user') {
|
||||
|
||||
@ -9,6 +9,13 @@
|
||||
:callbacks="data.callbacks"
|
||||
@close="close"
|
||||
/>
|
||||
<release-modal
|
||||
v-if="open === 'release'"
|
||||
:id="data.resource.id"
|
||||
:type="data.type"
|
||||
:name="name"
|
||||
@close="close"
|
||||
/>
|
||||
<report-modal
|
||||
v-if="open === 'report'"
|
||||
:id="data.resource.id"
|
||||
@ -31,6 +38,7 @@
|
||||
<script>
|
||||
import DeleteModal from '~/components/Modal/DeleteModal'
|
||||
import DisableModal from '~/components/Modal/DisableModal'
|
||||
import ReleaseModal from '~/components/ReleaseModal/ReleaseModal.vue'
|
||||
import ReportModal from '~/components/Modal/ReportModal'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
@ -38,6 +46,7 @@ export default {
|
||||
name: 'Modal',
|
||||
components: {
|
||||
DisableModal,
|
||||
ReleaseModal,
|
||||
ReportModal,
|
||||
DeleteModal,
|
||||
},
|
||||
|
||||
@ -33,6 +33,9 @@ describe('DisableModal.vue', () => {
|
||||
$apollo: {
|
||||
mutate: jest.fn().mockResolvedValue(),
|
||||
},
|
||||
location: {
|
||||
reload: jest.fn(),
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@ -4,9 +4,7 @@
|
||||
<p v-html="message" />
|
||||
|
||||
<template slot="footer">
|
||||
<ds-button class="cancel" @click="cancel">
|
||||
{{ $t('disable.cancel') }}
|
||||
</ds-button>
|
||||
<ds-button class="cancel" @click="cancel">{{ $t('disable.cancel') }}</ds-button>
|
||||
|
||||
<ds-button danger class="confirm" icon="exclamation-circle" @click="confirm">
|
||||
{{ $t('disable.submit') }}
|
||||
@ -70,6 +68,9 @@ export default {
|
||||
setTimeout(() => {
|
||||
this.$emit('close')
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
location.reload()
|
||||
}, 250)
|
||||
} catch (err) {
|
||||
this.$toast.error(err.message)
|
||||
}
|
||||
|
||||
175
webapp/components/ReleaseModal/ReleaseModal.spec.js
Normal file
175
webapp/components/ReleaseModal/ReleaseModal.spec.js
Normal file
@ -0,0 +1,175 @@
|
||||
import { shallowMount, mount, createLocalVue } from '@vue/test-utils'
|
||||
import ReleaseModal from './ReleaseModal.vue'
|
||||
import Styleguide from '@human-connection/styleguide'
|
||||
|
||||
const localVue = createLocalVue()
|
||||
|
||||
localVue.use(Styleguide)
|
||||
|
||||
describe('ReleaseModal.vue', () => {
|
||||
let mocks
|
||||
let propsData
|
||||
let wrapper
|
||||
let Wrapper
|
||||
|
||||
beforeEach(() => {
|
||||
propsData = {
|
||||
type: 'contribution',
|
||||
name: 'blah',
|
||||
id: 'c42',
|
||||
}
|
||||
mocks = {
|
||||
$filters: {
|
||||
truncate: a => a,
|
||||
},
|
||||
$toast: {
|
||||
success: () => {},
|
||||
error: () => {},
|
||||
},
|
||||
$t: jest.fn(),
|
||||
$apollo: {
|
||||
mutate: jest.fn().mockResolvedValue(),
|
||||
},
|
||||
location: {
|
||||
reload: jest.fn(),
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
describe('shallowMount', () => {
|
||||
Wrapper = () => {
|
||||
return shallowMount(ReleaseModal, {
|
||||
propsData,
|
||||
mocks,
|
||||
localVue,
|
||||
})
|
||||
}
|
||||
|
||||
describe('given a user', () => {
|
||||
beforeEach(() => {
|
||||
propsData = {
|
||||
type: 'user',
|
||||
id: 'u2',
|
||||
name: 'Bob Ross',
|
||||
}
|
||||
})
|
||||
|
||||
it('mentions user name', () => {
|
||||
Wrapper()
|
||||
const calls = mocks.$t.mock.calls
|
||||
const expected = [
|
||||
[
|
||||
'release.user.message',
|
||||
{
|
||||
name: 'Bob Ross',
|
||||
},
|
||||
],
|
||||
]
|
||||
expect(calls).toEqual(expect.arrayContaining(expected))
|
||||
})
|
||||
})
|
||||
|
||||
describe('given a contribution', () => {
|
||||
beforeEach(() => {
|
||||
propsData = {
|
||||
type: 'contribution',
|
||||
id: 'c3',
|
||||
name: 'This is some post title.',
|
||||
}
|
||||
})
|
||||
|
||||
it('mentions contribution title', () => {
|
||||
Wrapper()
|
||||
const calls = mocks.$t.mock.calls
|
||||
const expected = [
|
||||
[
|
||||
'release.contribution.message',
|
||||
{
|
||||
name: 'This is some post title.',
|
||||
},
|
||||
],
|
||||
]
|
||||
expect(calls).toEqual(expect.arrayContaining(expected))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('mount', () => {
|
||||
Wrapper = () => {
|
||||
return mount(ReleaseModal, {
|
||||
propsData,
|
||||
mocks,
|
||||
localVue,
|
||||
})
|
||||
}
|
||||
|
||||
beforeEach(jest.useFakeTimers)
|
||||
|
||||
describe('given id', () => {
|
||||
beforeEach(() => {
|
||||
propsData = {
|
||||
type: 'user',
|
||||
id: 'u4711',
|
||||
}
|
||||
})
|
||||
|
||||
describe('click cancel button', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
wrapper.find('button.cancel').trigger('click')
|
||||
})
|
||||
|
||||
it('does not emit "close" yet', () => {
|
||||
expect(wrapper.emitted().close).toBeFalsy()
|
||||
})
|
||||
|
||||
it('fades away', () => {
|
||||
expect(wrapper.vm.isOpen).toBe(false)
|
||||
})
|
||||
|
||||
describe('after timeout', () => {
|
||||
beforeEach(jest.runAllTimers)
|
||||
|
||||
it('does not call mutation', () => {
|
||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('emits close', () => {
|
||||
expect(wrapper.emitted().close).toBeTruthy()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('click confirm button', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
wrapper.find('button.confirm').trigger('click')
|
||||
})
|
||||
|
||||
it('calls mutation', () => {
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('passes id to mutation', () => {
|
||||
const calls = mocks.$apollo.mutate.mock.calls
|
||||
const [[{ variables }]] = calls
|
||||
expect(variables).toEqual({
|
||||
id: 'u4711',
|
||||
})
|
||||
})
|
||||
|
||||
it('fades away', () => {
|
||||
expect(wrapper.vm.isOpen).toBe(false)
|
||||
})
|
||||
|
||||
describe('after timeout', () => {
|
||||
beforeEach(jest.runAllTimers)
|
||||
|
||||
it('emits close', () => {
|
||||
expect(wrapper.emitted().close).toBeTruthy()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
77
webapp/components/ReleaseModal/ReleaseModal.vue
Normal file
77
webapp/components/ReleaseModal/ReleaseModal.vue
Normal file
@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<ds-modal :title="title" :is-open="isOpen" @cancel="cancel">
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<p v-html="message" />
|
||||
|
||||
<template slot="footer">
|
||||
<ds-button class="cancel" @click="cancel">{{ $t('release.cancel') }}</ds-button>
|
||||
|
||||
<ds-button danger class="confirm" icon="exclamation-circle" @click="confirm">
|
||||
{{ $t('release.submit') }}
|
||||
</ds-button>
|
||||
</template>
|
||||
</ds-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
name: { type: String, default: '' },
|
||||
type: { type: String, required: true },
|
||||
id: { type: String, required: true },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isOpen: true,
|
||||
success: false,
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return this.$t(`release.${this.type}.title`)
|
||||
},
|
||||
message() {
|
||||
const name = this.$filters.truncate(this.name, 30)
|
||||
return this.$t(`release.${this.type}.message`, { name })
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
cancel() {
|
||||
this.isOpen = false
|
||||
setTimeout(() => {
|
||||
this.$emit('close')
|
||||
}, 1000)
|
||||
},
|
||||
async confirm() {
|
||||
try {
|
||||
await this.$apollo.mutate({
|
||||
mutation: gql`
|
||||
mutation($id: ID!) {
|
||||
enable(id: $id)
|
||||
}
|
||||
`,
|
||||
variables: { id: this.id },
|
||||
})
|
||||
this.$toast.success(this.$t('release.success'))
|
||||
this.isOpen = false
|
||||
/*
|
||||
setTimeout(() => {
|
||||
location.reload()
|
||||
}, 1500)
|
||||
*/
|
||||
setTimeout(() => {
|
||||
this.$emit('close')
|
||||
}, 1000)
|
||||
setTimeout(() => {
|
||||
location.reload()
|
||||
}, 250)
|
||||
} catch (err) {
|
||||
this.$toast.error(err.message)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -257,5 +257,31 @@
|
||||
},
|
||||
"shoutButton": {
|
||||
"shouted": "empfohlen"
|
||||
},
|
||||
|
||||
"release": {
|
||||
"submit": "freigeben",
|
||||
"cancel": "Abbrechen",
|
||||
"success": "Erfolgreich freigegeben!",
|
||||
"user": {
|
||||
"title": "Nutzer freigeben",
|
||||
"type": "Nutzer",
|
||||
"message": "Bist du sicher, dass du den Nutzer \"<b>{name}</b>\" freigeben möchtest?"
|
||||
},
|
||||
"contribution": {
|
||||
"title": "Beitrag freigeben",
|
||||
"type": "Beitrag",
|
||||
"message": "Bist du sicher, dass du den Beitrag \"<b>{name}</b>\" freigeben möchtest?"
|
||||
},
|
||||
"comment": {
|
||||
"title": "Kommentar freigeben",
|
||||
"type": "Kommentar",
|
||||
"message": "Bist du sicher, dass du den Kommentar \"<b>{name}</b>\" freigeben möchtest?"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"avatar": {
|
||||
"submitted": "Upload erfolgreich"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,9 +258,29 @@
|
||||
"shoutButton": {
|
||||
"shouted": "shouted"
|
||||
},
|
||||
"release": {
|
||||
"submit": "Release",
|
||||
"cancel": "Cancel",
|
||||
"success": "Released successfully!",
|
||||
"user": {
|
||||
"title": "Release User",
|
||||
"type": "User",
|
||||
"message": "Do you really want to release the user \"<b>{name}</b>\"?"
|
||||
},
|
||||
"contribution": {
|
||||
"title": "Release Contribution",
|
||||
"type": "Contribution",
|
||||
"message": "Do you really want to release the contribution \"<b>{name}</b>\"?"
|
||||
},
|
||||
"comment": {
|
||||
"title": "Release Comment",
|
||||
"type": "Comment",
|
||||
"message": "Do you really want to release the comment from \"<b>{name}</b>\"?"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"avatar": {
|
||||
"submitted": "Upload successful"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user