Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions components/Author/Author.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
<template>
<div :class="{ disabled: disableLink, 'is-owner': isOwner, mask: maskUser }"
class="media hc__author"
@click="showProfile">
<div class="media-left" v-if="showAvatar">
class="media hc__author">
<div class="media-left" v-if="showAvatar" @click="showProfile">
<hc-avatar
:user="getUser"
:showOnlineStatus="true"
:imageKey="imageKey" />
</div>
<div class="media-content" v-if="showText">
<div class="media-content" @click="showProfile" v-if="showText">
<p class="title" v-if="!user">
{{ $t('component.contribution.creatorUnknown') }}
</p>
Expand All @@ -20,6 +19,8 @@
<hc-relative-date-time :dateTime="createdAt"></hc-relative-date-time>
</p>
</div>
<slot>
</slot>
</div>
</template>

Expand Down
127 changes: 127 additions & 0 deletions components/Global/Elements/BlockButton/BlockButton.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { shallowMount, mount, createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import BlockButton from './BlockButton'

const localVue = createLocalVue()

localVue.use(Vuex)

const propsData = {
foreignEntity: {
_id: 4711,
name: 'author'
},
isFollowing: false
}

const mocks = { $t: () => {} }

describe('BlockButton.vue', () => {
let actions
let getters
let store
let wrapper

beforeEach(() => {
getters = {
'feathers-vuex-usersettings/isBlacklisted': () => () => false,
'feathers-vuex-usersettings/isPending': () => false,
'feathers-vuex-usersettings/current': () => { return { blacklist: [] } }
}
actions = {
'feathers-vuex-usersettings/toggleBlacklist': jest.fn()
}
store = new Vuex.Store({
state: {}, getters, actions
})
})

test('renders', () => {
wrapper = shallowMount(BlockButton, { store, localVue, propsData, mocks })
expect(wrapper.is('hc-button-stub')).toBeTruthy()
})

describe('request pending', () => {
beforeEach(() => {
getters['feathers-vuex-usersettings/isPending'] = () => true
store = new Vuex.Store({state: {}, getters, actions})
wrapper = shallowMount(BlockButton, { store, localVue, propsData, mocks })
})

test('shows a loading spinner', () => {
expect(wrapper.find('hc-button-stub').attributes().isloading).toBeTruthy()
})

test('is disabled', () => {
expect(wrapper.find('hc-button-stub').attributes().disabled).toBeTruthy()
})
})

describe('no request pending', () => {
test('is enabled', () => {
wrapper = shallowMount(BlockButton, { store, localVue, propsData, mocks })
expect(wrapper.findAll('hc-button-stub')).toHaveLength(1)
expect(wrapper.find('hc-button-stub').attributes()).toEqual(expect.not.objectContaining({isloading: 'true'}))
})

describe('not blacklisted', () => {
test('shows a neutral ban icon', () => {
expect(wrapper.find('hc-icon-stub').classes()).not.toContain('is-danger')
})
})

describe('is blacklisted', () => {
beforeEach(() => {
getters['feathers-vuex-usersettings/isBlacklisted'] = () => () => true
store = new Vuex.Store({state: {}, getters, actions})
wrapper = shallowMount(BlockButton, { store, localVue, propsData, mocks })
})

test('gives visual feedback with a red colour', () => {
expect(wrapper.find('hc-icon-stub').classes()).toContain('is-danger')
})
})

test('dispatches feathers-vuex-usersettings/toggleBlacklist on click', () => {
wrapper = mount(BlockButton, {
store,
localVue,
mocks: {
$t: () => {},
$snackbar: {
open () { }
}
},
propsData
})
wrapper.find('button').trigger('click')
expect(actions['feathers-vuex-usersettings/toggleBlacklist']).toHaveBeenCalled()
})

describe('isFollowed === true', () => {
beforeEach(() => {
const props = Object.assign({}, propsData, {
isFollowing: true
})
wrapper = shallowMount(BlockButton, { store, localVue, propsData: props, mocks })
})

test('is disabled', () => {
expect(wrapper.find('hc-button-stub').attributes().disabled).toEqual('true')
})
})

describe('isFollowed === false', () => {
beforeEach(() => {
const props = Object.assign({}, propsData, {
isFollowing: false
})
wrapper = shallowMount(BlockButton, { store, localVue, propsData: props, mocks })
})

test('is disabled', () => {
expect(wrapper.find('hc-button-stub').attributes().disabled).toEqual(undefined)
})
})
})
})
66 changes: 66 additions & 0 deletions components/Global/Elements/BlockButton/BlockButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<template>
<hc-button color="button"
:disabled="isPending || isFollowing"
:isLoading="isPending"
@click="toggleBlacklist">
<template v-if="isBlacklisted()">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use computed properties

<hc-icon icon="ban" :class="['icon-left', 'is-danger']" /> {{ $t('component.blacklist.buttonLabelUnblock') }}
</template>
<template v-else>
<hc-icon icon="ban" class="icon-left" /> {{ $t('component.blacklist.buttonLabelBlock') }}
</template>
</hc-button>
</template>

<script>
import Icon from '~/components/Global/Elements/Icon/Icon.vue'
import Button from '~/components/Global/Elements/Button/Button.vue'
import { mapGetters } from 'vuex'

export default {
name: 'hc-block-button',
components: {
'hc-button': Button,
'hc-icon': Icon
},
props: {
foreignEntity: {
type: Object,
required: true
},
isFollowing: {
required: true
}
},
computed: {
...mapGetters({
isPending: 'feathers-vuex-usersettings/isPending',
})
},
methods: {
isBlacklisted () {
return this.$store.getters['feathers-vuex-usersettings/isBlacklisted'](this.foreignEntity)
},
async toggleBlacklist() {
let message
try {
await this.$store.dispatch('feathers-vuex-usersettings/toggleBlacklist', this.foreignEntity)
const translationKey = `component.blacklist.${this.isBlacklisted() ? 'blockSuccess' : 'unblockSuccess'}`
message = this.$t(translationKey, {
name: this.foreignEntity.name || this.$t('component.contribution.creatorUnknown')
})
} catch (error) {
message = this.$t('component.error.general')
throw (error)
} finally {
this.$snackbar.open({ message })
}
}
}

}
</script>

<style lang="scss" scoped>
@import "assets/styles/utilities";
</style>
85 changes: 85 additions & 0 deletions components/Global/Elements/Follow/FollowButtons.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { shallowMount, createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'
import FollowButtons from './FollowButtons'

const localVue = createLocalVue()

localVue.use(Vuex)

let propsData

const mocks = { $t: () => {} }

describe('FollowButtons.vue', () => {
let wrapper
let actions
let getters
let store
let currentUser

beforeEach(() => {
propsData = {
entity: {
_id: 4711,
name: 'author'
}
}
currentUser = {
_id: 42
}
getters = {
'connections/follow': () => {
return { isPending: false, isFollowing: false }
},
'feathers-vuex-usersettings/current': () => { return {} },
'feathers-vuex-usersettings/isPending': () => false,
'auth/user': () => { return currentUser }
}
actions = {
'connections/syncFollow': () => {
}
}
store = new Vuex.Store({
state: {}, getters, actions
})
})

test('renders', () => {
wrapper = shallowMount(FollowButtons, { store, localVue, propsData, mocks })
expect(wrapper.is('div')).toBeTruthy()
})

describe('showButtons === true', () => {
beforeEach(() => {
propsData.showButtons = true
})

describe('entity is not blacklisted', () => {
beforeEach(() => {
getters['feathers-vuex-usersettings/isBlacklisted'] = () => () => false
store = new Vuex.Store({
state: {}, getters, actions
})
})

test('follow button is enabled', () => {
wrapper = shallowMount(FollowButtons, { store, localVue, propsData, mocks })
expect(wrapper.find('hc-button-stub').attributes().disabled).toEqual(undefined)
})
})

describe('entity is blacklisted', () => {
beforeEach(() => {
getters['feathers-vuex-usersettings/isBlacklisted'] = () => () => true
store = new Vuex.Store({
state: {}, getters, actions
})
})

test('follow button is disabled', () => {
wrapper = shallowMount(FollowButtons, { store, localVue, propsData, mocks })
expect(wrapper.find('hc-button-stub').attributes().disabled).toEqual('true')
})
})
})
})
32 changes: 15 additions & 17 deletions components/Global/Elements/Follow/FollowButtons.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<div v-if="showButtons" class="columns is-mobile field has-text-centered">
<div class="column control has-text-centered">
<hc-button color="button is-fullwidth"
:class="{'is-primary': !follow.isLoading && !follow.isPending && !follow.isFollowing}"
:class="{'is-primary': !follow.isPending && !follow.isFollowing}"
@click="toggleFollow"
:disabled="follow.isPending"
:disabled="follow.isPending || this.isBlacklisted()"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont use this inside Templates.
Also is it possible to use a computed property instead of a method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@appinteractive I find it odd that this comment is still visible although the code has been altered a long time ago 🤔

Copy link
Member

@appinteractive appinteractive Nov 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to be a Microsoft Bug 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤣 🤣 🤣

:isLoading="follow.isPending">
<template v-if="follow.isFollowing">
<hc-icon icon="check" class="icon-left" /> {{ $t('component.follow.buttonLabelUnFollow') }}
Expand All @@ -29,25 +29,26 @@
</template>
</hc-button>
</div>
<div v-if="service === 'users'" class="column control has-text-centered" style="opacity: .25; pointer-events: none;">
<hc-button color="button" @click="toggleConnected" :disabled="true">
<template v-if="connected">
<hc-icon icon="user-times" class="icon-left" /> Trennen
</template>
<template v-else>
<hc-icon icon="user" class="icon-left" /> Verbinden
</template>
</hc-button>
<div v-if="service === 'users'" class="column is-mobile field has-text-centered">
<hc-block-button :foreignEntity="entity" :isFollowing="follow.isFollowing"/>
</div>
</div>
</div>
</template>

<script>
import { mapGetters } from 'vuex'
import BlockButton from '~/components/Global/Elements/BlockButton/BlockButton'
import Icon from '~/components/Global/Elements/Icon/Icon.vue'
import Button from '~/components/Global/Elements/Button/Button.vue'

export default {
name: 'hc-follow-buttons',
components: {
'hc-block-button': BlockButton,
'hc-button': Button,
'hc-icon': Icon
},
props: {
showButtons: {
type: Boolean,
Expand Down Expand Up @@ -83,6 +84,9 @@
})
},
methods: {
isBlacklisted(){
return this.$store.getters['feathers-vuex-usersettings/isBlacklisted'](this.entity)
},
async toggleFollow () {
if (this.follow._id) {
await this.$store.dispatch('connections/unfollow', {
Expand All @@ -106,12 +110,6 @@
})
})
}
},
toggleConnected () {
this.connected = !this.connected
this.$snackbar.open({
message: 'Connected!'
})
}
}
}
Expand Down
Loading