mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Merge pull request #535 from Human-Connection/463-delete-socialMedia
Delete SocialMedia
This commit is contained in:
commit
a9860c49fc
@ -75,6 +75,7 @@ const permissions = shield({
|
|||||||
DeleteBadge: isAdmin,
|
DeleteBadge: isAdmin,
|
||||||
AddUserBadges: isAdmin,
|
AddUserBadges: isAdmin,
|
||||||
CreateSocialMedia: isAuthenticated,
|
CreateSocialMedia: isAuthenticated,
|
||||||
|
DeleteSocialMedia: isAuthenticated,
|
||||||
// AddBadgeRewarded: isAdmin,
|
// AddBadgeRewarded: isAdmin,
|
||||||
// RemoveBadgeRewarded: isAdmin,
|
// RemoveBadgeRewarded: isAdmin,
|
||||||
reward: isAdmin,
|
reward: isAdmin,
|
||||||
|
|||||||
@ -3,6 +3,9 @@ import { neo4jgraphql } from 'neo4j-graphql-js'
|
|||||||
export default {
|
export default {
|
||||||
Mutation: {
|
Mutation: {
|
||||||
CreateSocialMedia: async (object, params, context, resolveInfo) => {
|
CreateSocialMedia: async (object, params, context, resolveInfo) => {
|
||||||
|
/**
|
||||||
|
* TODO?: Creates double Nodes!
|
||||||
|
*/
|
||||||
const socialMedia = await neo4jgraphql(object, params, context, resolveInfo, false)
|
const socialMedia = await neo4jgraphql(object, params, context, resolveInfo, false)
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
await session.run(
|
await session.run(
|
||||||
@ -15,6 +18,11 @@ export default {
|
|||||||
)
|
)
|
||||||
session.close()
|
session.close()
|
||||||
|
|
||||||
|
return socialMedia
|
||||||
|
},
|
||||||
|
DeleteSocialMedia: async (object, params, context, resolveInfo) => {
|
||||||
|
const socialMedia = await neo4jgraphql(object, params, context, resolveInfo, false)
|
||||||
|
|
||||||
return socialMedia
|
return socialMedia
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,9 +7,18 @@ const factory = Factory()
|
|||||||
describe('CreateSocialMedia', () => {
|
describe('CreateSocialMedia', () => {
|
||||||
let client
|
let client
|
||||||
let headers
|
let headers
|
||||||
const mutation = `
|
const mutationC = `
|
||||||
mutation($url: String!) {
|
mutation($url: String!) {
|
||||||
CreateSocialMedia(url: $url) {
|
CreateSocialMedia(url: $url) {
|
||||||
|
id
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
const mutationD = `
|
||||||
|
mutation($id: ID!) {
|
||||||
|
DeleteSocialMedia(id: $id) {
|
||||||
|
id
|
||||||
url
|
url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -30,20 +39,63 @@ describe('CreateSocialMedia', () => {
|
|||||||
await factory.cleanDatabase()
|
await factory.cleanDatabase()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('unauthenticated', () => {
|
||||||
|
it('throws authorization error', async () => {
|
||||||
|
client = new GraphQLClient(host)
|
||||||
|
const variables = { url: 'http://nsosp.org' }
|
||||||
|
await expect(
|
||||||
|
client.request(mutationC, variables)
|
||||||
|
).rejects.toThrow('Not Authorised')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('authenticated', () => {
|
describe('authenticated', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
headers = await login({ email: 'test@example.org', password: '1234' })
|
headers = await login({ email: 'test@example.org', password: '1234' })
|
||||||
client = new GraphQLClient(host, { headers })
|
client = new GraphQLClient(host, { headers })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('creates social media with correct URL', async () => {
|
||||||
|
const variables = { url: 'http://nsosp.org' }
|
||||||
|
await expect(
|
||||||
|
client.request(mutationC, variables)
|
||||||
|
).resolves.toEqual(expect.objectContaining({
|
||||||
|
CreateSocialMedia: {
|
||||||
|
id: expect.any(String),
|
||||||
|
url: 'http://nsosp.org'
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('deletes social media', async () => {
|
||||||
|
const creationVariables = { url: 'http://nsosp.org' }
|
||||||
|
const { CreateSocialMedia } = await client.request(mutationC, creationVariables)
|
||||||
|
const { id } = CreateSocialMedia
|
||||||
|
|
||||||
|
const deletionVariables = { id }
|
||||||
|
const expected = {
|
||||||
|
DeleteSocialMedia: {
|
||||||
|
id: id,
|
||||||
|
url: 'http://nsosp.org'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await expect(
|
||||||
|
client.request(mutationD, deletionVariables)
|
||||||
|
).resolves.toEqual(expected)
|
||||||
|
})
|
||||||
|
|
||||||
it('rejects empty string', async () => {
|
it('rejects empty string', async () => {
|
||||||
const variables = { url: '' }
|
const variables = { url: '' }
|
||||||
await expect(client.request(mutation, variables)).rejects.toThrow('Input is not a URL')
|
await expect(
|
||||||
|
client.request(mutationC, variables)
|
||||||
|
).rejects.toThrow('Input is not a URL')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('validates URLs', async () => {
|
it('validates URLs', async () => {
|
||||||
const variables = { url: 'not-a-url' }
|
const variables = { url: 'not-a-url' }
|
||||||
await expect(client.request(mutation, variables)).rejects.toThrow('Input is not a URL')
|
await expect(
|
||||||
|
client.request(mutationC, variables)
|
||||||
|
).rejects.toThrow('Input is not a URL')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -77,7 +77,7 @@ Then('I should be on the {string} page', page => {
|
|||||||
.should('contain', 'Social media')
|
.should('contain', 'Social media')
|
||||||
})
|
})
|
||||||
|
|
||||||
Then('I add a social media link', () => {
|
When('I add a social media link', () => {
|
||||||
cy.get("input[name='social-media']")
|
cy.get("input[name='social-media']")
|
||||||
.type('https://freeradical.zone/peter-pan')
|
.type('https://freeradical.zone/peter-pan')
|
||||||
.get('button')
|
.get('button')
|
||||||
@ -87,7 +87,7 @@ Then('I add a social media link', () => {
|
|||||||
|
|
||||||
Then('it gets saved successfully', () => {
|
Then('it gets saved successfully', () => {
|
||||||
cy.get('.iziToast-message')
|
cy.get('.iziToast-message')
|
||||||
.should('contain', 'Updated user')
|
.should('contain', 'Added social media')
|
||||||
})
|
})
|
||||||
|
|
||||||
Then('the new social media link shows up on the page', () => {
|
Then('the new social media link shows up on the page', () => {
|
||||||
@ -110,3 +110,13 @@ Then('they should be able to see my social media links', () => {
|
|||||||
.get('a[href="https://freeradical.zone/peter-pan"]')
|
.get('a[href="https://freeradical.zone/peter-pan"]')
|
||||||
.should('have.length', 1)
|
.should('have.length', 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
When('I delete a social media link', () => {
|
||||||
|
cy.get("a[name='delete']")
|
||||||
|
.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
Then('it gets deleted successfully', () => {
|
||||||
|
cy.get('.iziToast-message')
|
||||||
|
.should('contain', 'Deleted social media')
|
||||||
|
})
|
||||||
|
|||||||
@ -19,3 +19,11 @@ Feature: List Social Media Accounts
|
|||||||
Given I have added a social media link
|
Given I have added a social media link
|
||||||
When people visit my profile page
|
When people visit my profile page
|
||||||
Then they should be able to see my social media links
|
Then they should be able to see my social media links
|
||||||
|
|
||||||
|
Scenario: Deleting Social Media
|
||||||
|
Given I am on the "settings" page
|
||||||
|
And I click on the "Social media" link
|
||||||
|
Then I should be on the "/settings/my-social-media" page
|
||||||
|
Given I have added a social media link
|
||||||
|
When I delete a social media link
|
||||||
|
Then it gets deleted successfully
|
||||||
|
|||||||
@ -65,8 +65,10 @@
|
|||||||
},
|
},
|
||||||
"social-media": {
|
"social-media": {
|
||||||
"name": "Soziale Medien",
|
"name": "Soziale Medien",
|
||||||
|
"placeholder": "Füge eine Social-Media URL hinzu",
|
||||||
"submit": "Link hinzufügen",
|
"submit": "Link hinzufügen",
|
||||||
"success": "Profil aktualisiert"
|
"successAdd": "Social-Media hinzugefügt. Profil aktualisiert!",
|
||||||
|
"successDelete": "Social-Media gelöscht. Profil aktualisiert!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
|
|||||||
@ -65,8 +65,10 @@
|
|||||||
},
|
},
|
||||||
"social-media": {
|
"social-media": {
|
||||||
"name": "Social media",
|
"name": "Social media",
|
||||||
|
"placeholder": "Add social media url",
|
||||||
"submit": "Add link",
|
"submit": "Add link",
|
||||||
"success": "Updated user profile"
|
"successAdd": "Added social media. Updated user profile!",
|
||||||
|
"successDelete": "Deleted social media. Updated user profile!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
|
|||||||
@ -71,6 +71,40 @@ describe('my-social-media.vue', () => {
|
|||||||
const socialMediaLink = wrapper.find('a').attributes().href
|
const socialMediaLink = wrapper.find('a').attributes().href
|
||||||
expect(socialMediaLink).toBe(socialMediaUrl)
|
expect(socialMediaLink).toBe(socialMediaUrl)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mocks = {
|
||||||
|
$t: jest.fn(),
|
||||||
|
$apollo: {
|
||||||
|
mutate: jest
|
||||||
|
.fn()
|
||||||
|
.mockRejectedValue({ message: 'Ouch!' })
|
||||||
|
.mockResolvedValueOnce({
|
||||||
|
data: { DeleteSocialMeda: { id: 's1', url: socialMediaUrl } }
|
||||||
|
})
|
||||||
|
},
|
||||||
|
$toast: {
|
||||||
|
error: jest.fn(),
|
||||||
|
success: jest.fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getters = {
|
||||||
|
'auth/user': () => {
|
||||||
|
return {
|
||||||
|
socialMedia: [{ id: 's1', url: socialMediaUrl }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('displays a trash sympol after a social media and allows the user to delete it', () => {
|
||||||
|
wrapper = Wrapper()
|
||||||
|
const deleteSelector = wrapper.find({ name: 'delete' })
|
||||||
|
expect(deleteSelector).toEqual({ selector: 'Component' })
|
||||||
|
const icon = wrapper.find({ name: 'trash' })
|
||||||
|
icon.trigger('click')
|
||||||
|
expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('currentUser does not have a social media account linked', () => {
|
describe('currentUser does not have a social media account linked', () => {
|
||||||
|
|||||||
@ -8,9 +8,12 @@
|
|||||||
<ds-list>
|
<ds-list>
|
||||||
<ds-list-item
|
<ds-list-item
|
||||||
v-for="link in socialMediaLinks"
|
v-for="link in socialMediaLinks"
|
||||||
:key="link.url"
|
:key="link.id"
|
||||||
>
|
>
|
||||||
<a :href="link.url">
|
<a
|
||||||
|
:href="link.url"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
<img
|
<img
|
||||||
:src="link.favicon"
|
:src="link.favicon"
|
||||||
alt="Social Media link"
|
alt="Social Media link"
|
||||||
@ -19,26 +22,39 @@
|
|||||||
>
|
>
|
||||||
{{ link.url }}
|
{{ link.url }}
|
||||||
</a>
|
</a>
|
||||||
|
<span class="layout-leave-active">|</span>
|
||||||
|
<ds-icon
|
||||||
|
name="edit"
|
||||||
|
class="layout-leave-active"
|
||||||
|
/>
|
||||||
|
<a
|
||||||
|
name="delete"
|
||||||
|
@click="handleDeleteSocialMedia(link)"
|
||||||
|
>
|
||||||
|
<ds-icon name="trash" />
|
||||||
|
</a>
|
||||||
</ds-list-item>
|
</ds-list-item>
|
||||||
</ds-list>
|
</ds-list>
|
||||||
</ds-space>
|
</ds-space>
|
||||||
<div>
|
|
||||||
<ds-input
|
|
||||||
v-model="value"
|
|
||||||
placeholder="Add social media url"
|
|
||||||
name="social-media"
|
|
||||||
:schema="{type: 'url'}"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<ds-space margin-top="base">
|
<ds-space margin-top="base">
|
||||||
<div>
|
<div>
|
||||||
<ds-button
|
<ds-input
|
||||||
primary
|
v-model="value"
|
||||||
@click="handleAddSocialMedia"
|
:placeholder="$t('settings.social-media.placeholder')"
|
||||||
>
|
name="social-media"
|
||||||
{{ $t('settings.social-media.submit') }}
|
:schema="{type: 'url'}"
|
||||||
</ds-button>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<ds-space margin-top="base">
|
||||||
|
<div>
|
||||||
|
<ds-button
|
||||||
|
primary
|
||||||
|
@click="handleAddSocialMedia"
|
||||||
|
>
|
||||||
|
{{ $t('settings.social-media.submit') }}
|
||||||
|
</ds-button>
|
||||||
|
</div>
|
||||||
|
</ds-space>
|
||||||
</ds-space>
|
</ds-space>
|
||||||
</ds-card>
|
</ds-card>
|
||||||
</template>
|
</template>
|
||||||
@ -59,13 +75,13 @@ export default {
|
|||||||
socialMediaLinks() {
|
socialMediaLinks() {
|
||||||
const { socialMedia = [] } = this.currentUser
|
const { socialMedia = [] } = this.currentUser
|
||||||
return socialMedia.map(socialMedia => {
|
return socialMedia.map(socialMedia => {
|
||||||
const { url } = socialMedia
|
const { id, url } = socialMedia
|
||||||
const matches = url.match(
|
const matches = url.match(
|
||||||
/^(?:https?:\/\/)?(?:[^@\n])?(?:www\.)?([^:\/\n?]+)/g
|
/^(?:https?:\/\/)?(?:[^@\n])?(?:www\.)?([^:\/\n?]+)/g
|
||||||
)
|
)
|
||||||
const [domain] = matches || []
|
const [domain] = matches || []
|
||||||
const favicon = domain ? `${domain}/favicon.ico` : null
|
const favicon = domain ? `${domain}/favicon.ico` : null
|
||||||
return { url, favicon }
|
return { id, url, favicon }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -79,6 +95,7 @@ export default {
|
|||||||
mutation: gql`
|
mutation: gql`
|
||||||
mutation($url: String!) {
|
mutation($url: String!) {
|
||||||
CreateSocialMedia(url: $url) {
|
CreateSocialMedia(url: $url) {
|
||||||
|
id
|
||||||
url
|
url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,11 +114,51 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(
|
.then(() => {
|
||||||
this.$toast.success(this.$t('settings.social-media.success')),
|
this.$toast.success(this.$t('settings.social-media.successAdd')),
|
||||||
(this.value = '')
|
(this.value = '')
|
||||||
)
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.$toast.error(error.message)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleDeleteSocialMedia(link) {
|
||||||
|
this.$apollo
|
||||||
|
.mutate({
|
||||||
|
mutation: gql`
|
||||||
|
mutation($id: ID!) {
|
||||||
|
DeleteSocialMedia(id: $id) {
|
||||||
|
id
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
variables: {
|
||||||
|
id: link.id
|
||||||
|
},
|
||||||
|
update: (store, { data }) => {
|
||||||
|
const socialMedia = this.currentUser.socialMedia.filter(
|
||||||
|
element => element.id !== link.id
|
||||||
|
)
|
||||||
|
this.setCurrentUser({
|
||||||
|
...this.currentUser,
|
||||||
|
socialMedia
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.$toast.success(this.$t('settings.social-media.successDelete'))
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.$toast.error(error.message)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.layout-leave-active {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user