mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Add stories/specs for ReportList
This commit is contained in:
parent
d0a18fded8
commit
a59e72d8a8
77
webapp/components/features/ReportList/ReportList.spec.js
Normal file
77
webapp/components/features/ReportList/ReportList.spec.js
Normal file
@ -0,0 +1,77 @@
|
||||
import { config, mount } from '@vue/test-utils'
|
||||
import Vuex from 'vuex'
|
||||
import ReportList from './ReportList'
|
||||
import { reports } from './ReportList.story'
|
||||
import ReportsTable from '~/components/features/ReportsTable/ReportsTable'
|
||||
import DropdownFilter from '~/components/DropdownFilter/DropdownFilter'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
config.stubs['client-only'] = '<span><slot /></span>'
|
||||
config.stubs['nuxt-link'] = '<span><slot /></span>'
|
||||
|
||||
describe('ReportList', () => {
|
||||
let mocks, mutations, getters, wrapper
|
||||
|
||||
beforeEach(() => {
|
||||
mocks = {
|
||||
$apollo: {
|
||||
mutate: jest
|
||||
.fn()
|
||||
.mockResolvedValueOnce({
|
||||
data: { review: { disable: true, resourceId: 'some-resource', closed: true } },
|
||||
})
|
||||
.mockRejectedValue({ message: 'Unable to review' }),
|
||||
},
|
||||
$t: jest.fn(),
|
||||
$toast: {
|
||||
error: jest.fn(message => message),
|
||||
},
|
||||
}
|
||||
mutations = {
|
||||
'modal/SET_OPEN': jest.fn().mockResolvedValueOnce(),
|
||||
}
|
||||
getters = {
|
||||
'auth/user': () => {
|
||||
return { slug: 'awesome-user' }
|
||||
},
|
||||
'auth/isModerator': () => true,
|
||||
}
|
||||
})
|
||||
|
||||
describe('mount', () => {
|
||||
const Wrapper = () => {
|
||||
const store = new Vuex.Store({
|
||||
mutations,
|
||||
getters,
|
||||
})
|
||||
return mount(ReportList, { mocks, localVue, store })
|
||||
}
|
||||
|
||||
describe('renders children components', () => {
|
||||
beforeEach(async () => {
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('renders DropdownFilter', () => {
|
||||
expect(wrapper.find(DropdownFilter).exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders ReportsTable', () => {
|
||||
expect(wrapper.find(ReportsTable).exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('confirm is emitted by reports table', () => {
|
||||
beforeEach(async () => {
|
||||
wrapper = Wrapper()
|
||||
wrapper.setData({ reports })
|
||||
wrapper.find(ReportsTable).vm.$emit('confirm', reports[0])
|
||||
})
|
||||
|
||||
it('calls modal/SET_OPEN', () => {
|
||||
expect(mutations['modal/SET_OPEN']).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
193
webapp/components/features/ReportList/ReportList.story.js
Normal file
193
webapp/components/features/ReportList/ReportList.story.js
Normal file
@ -0,0 +1,193 @@
|
||||
import { storiesOf } from '@storybook/vue'
|
||||
import { withA11y } from '@storybook/addon-a11y'
|
||||
import { action } from '@storybook/addon-actions'
|
||||
import { post } from '~/components/PostCard/PostCard.story.js'
|
||||
import { user } from '~/components/User/User.story.js'
|
||||
import helpers from '~/storybook/helpers'
|
||||
import ReportList from './ReportList'
|
||||
import DropdownFilter from '~/components/DropdownFilter/DropdownFilter'
|
||||
import ReportsTable from '~/components/features/ReportsTable/ReportsTable'
|
||||
helpers.init()
|
||||
|
||||
export const reports = [
|
||||
{
|
||||
__typename: 'Report',
|
||||
closed: false,
|
||||
createdAt: '2019-10-29T15:36:02.106Z',
|
||||
updatedAt: '2019-12-02T15:56:35.651Z',
|
||||
disable: false,
|
||||
filed: [
|
||||
{
|
||||
__typename: 'FILED',
|
||||
createdAt: '2019-10-02T15:56:35.676Z',
|
||||
reasonCategory: 'pornographic_content_links',
|
||||
reasonDescription: 'This comment is porno!!!',
|
||||
submitter: {
|
||||
...user,
|
||||
name: 'Community moderator',
|
||||
id: 'community-moderator',
|
||||
slug: 'community-moderator',
|
||||
},
|
||||
},
|
||||
],
|
||||
resource: {
|
||||
__typename: 'Comment',
|
||||
id: 'b6b38937-3efc-4d5e-b12c-549e4d6551a5',
|
||||
createdAt: '2019-10-29T15:38:25.184Z',
|
||||
updatedAt: '2019-10-30T15:38:25.184Z',
|
||||
disabled: false,
|
||||
deleted: false,
|
||||
content:
|
||||
'<p><a class="mention" href="/profile/u1" data-mention-id="u1" target="_blank">@peter-lustig</a> </p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Turpis egestas pretium aenean pharetra magna ac placerat. Tempor id eu nisl nunc mi ipsum faucibus vitae. Nibh praesent tristique magna sit amet purus gravida quis blandit. Magna eget est lorem ipsum dolor. In fermentum posuere urna nec. Eleifend donec pretium vulputate sapien nec sagittis aliquam. Augue interdum velit euismod in pellentesque. Id diam maecenas ultricies mi eget mauris pharetra. Donec pretium vulputate sapien nec. Dolor morbi non arcu risus quis varius quam quisque. Blandit turpis cursus in hac habitasse. Est ultricies integer quis auctor elit sed vulputate mi sit. Nunc consequat interdum varius sit amet mattis vulputate enim. Semper feugiat nibh sed pulvinar. Eget felis eget nunc lobortis mattis aliquam. Ultrices vitae auctor eu augue. Tellus molestie nunc non blandit massa enim nec dui. Pharetra massa massa ultricies mi quis hendrerit dolor. Nisl suscipit adipiscing bibendum est ultricies integer.</p>',
|
||||
contentExcerpt:
|
||||
'<p><a href="/profile/u1" target="_blank">@peter-lustig</a> </p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Turpis egestas pretium aenean pharetra …</p>',
|
||||
post,
|
||||
author: user,
|
||||
},
|
||||
reviewed: [
|
||||
{
|
||||
updatedAt: '2019-10-30T15:38:25.184Z',
|
||||
moderator: {
|
||||
__typename: 'User',
|
||||
...user,
|
||||
name: 'Moderator',
|
||||
id: 'moderator',
|
||||
slug: 'moderator',
|
||||
},
|
||||
},
|
||||
{
|
||||
updatedAt: '2019-10-29T15:38:25.184Z',
|
||||
moderator: {
|
||||
__typename: 'User',
|
||||
...user,
|
||||
name: 'Peter Lustig',
|
||||
id: 'u3',
|
||||
slug: 'peter-lustig',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
__typename: 'Report',
|
||||
closed: false,
|
||||
createdAt: '2019-10-31T15:36:02.106Z',
|
||||
updatedAt: '2019-12-03T15:56:35.651Z',
|
||||
disable: true,
|
||||
filed: [
|
||||
{
|
||||
__typename: 'FILED',
|
||||
createdAt: '2019-10-31T15:36:02.106Z',
|
||||
reasonCategory: 'discrimination_etc',
|
||||
reasonDescription: 'This post is bigoted',
|
||||
submitter: {
|
||||
...user,
|
||||
name: 'Modertation team',
|
||||
id: 'moderation-team',
|
||||
slug: 'moderation-team',
|
||||
},
|
||||
},
|
||||
],
|
||||
resource: {
|
||||
__typename: 'Post',
|
||||
author: {
|
||||
...user,
|
||||
id: 'u7',
|
||||
name: 'Dagobert',
|
||||
slug: 'dagobert',
|
||||
},
|
||||
deleted: false,
|
||||
disabled: false,
|
||||
id: 'p2',
|
||||
slug: 'bigoted-post',
|
||||
title: "I'm a bigoted post!",
|
||||
},
|
||||
reviewed: null,
|
||||
},
|
||||
{
|
||||
__typename: 'Report',
|
||||
closed: true,
|
||||
createdAt: '2019-10-30T15:36:02.106Z',
|
||||
updatedAt: '2019-12-01T15:56:35.651Z',
|
||||
disable: true,
|
||||
filed: [
|
||||
{
|
||||
__typename: 'FILED',
|
||||
createdAt: '2019-10-30T15:36:02.106Z',
|
||||
reasonCategory: 'discrimination_etc',
|
||||
reasonDescription: 'this user is attacking me for who I am!',
|
||||
submitter: {
|
||||
...user,
|
||||
name: 'Helpful user',
|
||||
id: 'helpful-user',
|
||||
slug: 'helpful-user',
|
||||
},
|
||||
},
|
||||
],
|
||||
resource: {
|
||||
__typename: 'User',
|
||||
commentedCount: 0,
|
||||
contributionsCount: 0,
|
||||
deleted: false,
|
||||
disabled: true,
|
||||
followedByCount: 0,
|
||||
id: 'u5',
|
||||
name: 'Abusive user',
|
||||
slug: 'abusive-user',
|
||||
},
|
||||
reviewed: [
|
||||
{
|
||||
updatedAt: '2019-12-01T15:56:35.651Z',
|
||||
moderator: {
|
||||
__typename: 'User',
|
||||
...user,
|
||||
name: 'Peter Lustig',
|
||||
id: 'u3',
|
||||
slug: 'peter-lustig',
|
||||
},
|
||||
},
|
||||
{
|
||||
updatedAt: '2019-11-30T15:56:35.651Z',
|
||||
moderator: {
|
||||
__typename: 'User',
|
||||
...user,
|
||||
name: 'Moderator',
|
||||
id: 'moderator',
|
||||
slug: 'moderator',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
const unreviewedReports = reports.filter(report => !report.reviewed)
|
||||
const reviewedReports = reports.filter(report => report.reviewed)
|
||||
const closedReports = reports.filter(report => report.closed)
|
||||
const filterOptions = [
|
||||
{ label: 'All', value: reports },
|
||||
{ label: 'Unreviewed', value: unreviewedReports },
|
||||
{ label: 'Reviewed', value: reviewedReports },
|
||||
{ label: 'Closed', value: closedReports },
|
||||
]
|
||||
|
||||
storiesOf('ReportList', module)
|
||||
.addDecorator(withA11y)
|
||||
.addDecorator(helpers.layout)
|
||||
.add('with reports', () => ({
|
||||
components: { ReportList, DropdownFilter, ReportsTable },
|
||||
store: helpers.store,
|
||||
data: () => ({
|
||||
filterOptions,
|
||||
selected: filterOptions[0].label,
|
||||
reports,
|
||||
}),
|
||||
methods: {
|
||||
openModal: action('openModal'),
|
||||
filter: action('filter'),
|
||||
},
|
||||
template: `<ds-card>
|
||||
<div class="reports-header">
|
||||
<h3 class="title">Reports</h3>
|
||||
<dropdown-filter @filter="filter" :filterOptions="filterOptions" :selected="selected" />
|
||||
</div>
|
||||
<reports-table :reports="reports" @confirm="openModal" />
|
||||
</ds-card>`,
|
||||
}))
|
||||
142
webapp/components/features/ReportList/ReportList.vue
Normal file
142
webapp/components/features/ReportList/ReportList.vue
Normal file
@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<ds-card>
|
||||
<div class="reports-header">
|
||||
<h3 class="title">{{ $t('moderation.reports.name') }}</h3>
|
||||
<client-only>
|
||||
<dropdown-filter @filter="filter" :filterOptions="filterOptions" :selected="selected" />
|
||||
</client-only>
|
||||
</div>
|
||||
<reports-table :reports="reports" @confirm="openModal" />
|
||||
</ds-card>
|
||||
</template>
|
||||
<script>
|
||||
import { mapMutations } from 'vuex'
|
||||
import DropdownFilter from '~/components/DropdownFilter/DropdownFilter'
|
||||
import ReportsTable from '~/components/features/ReportsTable/ReportsTable'
|
||||
import { reportsListQuery, reviewMutation } from '~/graphql/Moderation.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
DropdownFilter,
|
||||
ReportsTable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
reports: [],
|
||||
allReports: [],
|
||||
unreviewedReports: [],
|
||||
reviewedReports: [],
|
||||
closedReports: [],
|
||||
selected: this.$t('moderation.reports.filterLabel.all'),
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filterOptions() {
|
||||
return [
|
||||
{ label: this.$t('moderation.reports.filterLabel.all'), value: this.allReports },
|
||||
{
|
||||
label: this.$t('moderation.reports.filterLabel.unreviewed'),
|
||||
value: this.unreviewedReports,
|
||||
},
|
||||
{ label: this.$t('moderation.reports.filterLabel.reviewed'), value: this.reviewedReports },
|
||||
{ label: this.$t('moderation.reports.filterLabel.closed'), value: this.closedReports },
|
||||
]
|
||||
},
|
||||
modalData() {
|
||||
return function(report) {
|
||||
const identStart =
|
||||
'moderation.reports.decideModal.' +
|
||||
report.resource.__typename +
|
||||
'.' +
|
||||
(report.resource.disabled ? 'disable' : 'enable')
|
||||
return {
|
||||
name: 'confirm',
|
||||
data: {
|
||||
type: report.resource.__typename,
|
||||
resource: report.resource,
|
||||
modalData: {
|
||||
titleIdent: identStart + '.title',
|
||||
messageIdent: identStart + '.message',
|
||||
messageParams: {
|
||||
name:
|
||||
report.resource.name ||
|
||||
this.$filters.truncate(report.resource.title, 30) ||
|
||||
this.$filters.truncate(
|
||||
this.$filters.removeHtml(report.resource.contentExcerpt),
|
||||
30,
|
||||
),
|
||||
},
|
||||
buttons: {
|
||||
confirm: {
|
||||
danger: true,
|
||||
icon: report.resource.disabled ? 'eye-slash' : 'eye',
|
||||
textIdent: 'moderation.reports.decideModal.submit',
|
||||
callback: () => {
|
||||
this.confirmCallback(report.resource)
|
||||
},
|
||||
},
|
||||
cancel: {
|
||||
icon: 'close',
|
||||
textIdent: 'moderation.reports.decideModal.cancel',
|
||||
callback: () => {},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
commitModalData: 'modal/SET_OPEN',
|
||||
}),
|
||||
filter(option) {
|
||||
this.reports = option.value
|
||||
this.selected = option.label
|
||||
},
|
||||
async confirmCallback(resource) {
|
||||
const { disabled: disable, id: resourceId } = resource
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: reviewMutation(),
|
||||
variables: { disable, resourceId, closed: true },
|
||||
})
|
||||
.then(() => {
|
||||
this.$toast.success(this.$t('moderation.reports.DecisionSuccess'))
|
||||
this.$apollo.queries.reportsList.refetch()
|
||||
})
|
||||
.catch(error => this.$toast.error(error.message))
|
||||
},
|
||||
openModal(report) {
|
||||
this.commitModalData(this.modalData(report))
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
reportsList: {
|
||||
query: reportsListQuery(),
|
||||
update({ reports }) {
|
||||
this.reports = reports
|
||||
this.allReports = reports
|
||||
this.unreviewedReports = reports.filter(report => !report.reviewed)
|
||||
this.reviewedReports = reports.filter(report => report.reviewed)
|
||||
this.closedReports = reports.filter(report => report.closed)
|
||||
},
|
||||
fetchPolicy: 'cache-and-network',
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.reports-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: $space-small 0;
|
||||
|
||||
> .title {
|
||||
margin: 0;
|
||||
font-size: $font-size-large;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
x
Reference in New Issue
Block a user