Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve cypress coverage #1837

Merged
merged 8 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Comment extends React.Component {

render() {
return (
<Card sx={{ mb: [3], minWidth: '35em' }}>
<Card sx={{ mb: [3], minWidth: '35em' }} data-test-id="pending-comment">
<Box>
<Text sx={{ mb: [3], color: 'red', fontSize: 12 }}>{this.props.comment.active ? null : 'Comment flagged as toxic by Jigsaw Perspective API. Comment not shown to participants. Accept to override.'}</Text>
<Text sx={{ mb: [3] }}>{this.props.comment.txt}</Text>
Expand All @@ -44,7 +44,7 @@ class Comment extends React.Component {
</Button>
) : null}
{this.props.rejectButton ? (
<Button onClick={this.onRejectClicked.bind(this)}>
<Button onClick={this.onRejectClicked.bind(this)} data-test-id="reject-comment">
{this.props.rejectButtonText}
</Button>
) : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class CommentModeration extends React.Component {
</Heading>
<Flex sx={{ mb: [4] }}>
<Link
data-test-id="mod-queue"
sx={{
mr: [4],
variant: url ? 'links.nav' : 'links.activeNav'
Expand All @@ -80,6 +81,7 @@ class CommentModeration extends React.Component {
: null}
</Link>
<Link
data-test-id="filter-approved"
sx={{
mr: [4],
variant: url === 'accepted' ? 'links.activeNav' : 'links.nav'
Expand All @@ -91,6 +93,7 @@ class CommentModeration extends React.Component {
: null}
</Link>
<Link
data-test-id="filter-rejected"
sx={{
mr: [4],
variant: url === 'rejected' ? 'links.activeNav' : 'links.nav'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ModerateCommentsAccepted extends React.Component {

render() {
return (
<div>
<div data-test-id="approved-comments">
{this.props.accepted_comments !== null
? this.createCommentMarkup()
: 'Loading accepted comments...'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ModerateCommentsRejected extends React.Component {

render() {
return (
<div>
<div data-test-id="rejected-comments">
{this.props.rejected_comments !== null
? this.createCommentMarkup()
: 'Loading rejected comments...'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class ModerateCommentsTodo extends React.Component {
render() {
const max = 100;
return (
<div>
<div data-test-id="pending-comment">
<div>
<p> Displays maximum {max} comments </p>
{this.props.unmoderated_comments !== null
Expand Down
1 change: 1 addition & 0 deletions client-admin/src/components/conversation-admin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class ConversationAdminContainer extends React.Component {
sx={{
variant: url === 'comments' ? 'links.activeNav' : 'links.nav'
}}
data-test-id="moderate-comments"
to={`${match.url}/comments`}>
Moderate
</Link>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import PropTypes from 'prop-types'
import Url from '../../../util/url'
import { connect } from 'react-redux'
import { Heading, Box, Button } from 'theme-ui'
import { populateZidMetadataStore } from '../../../actions'
import ComponentHelpers from '../../../util/component-helpers'
import NoPermission from '../no-permission'

Expand All @@ -31,11 +32,24 @@ class ReportsList extends React.Component {
})
})
}

componentDidMount() {
const { zid_metadata } = this.props

// eslint-disable-next-line react/prop-types
this.props.dispatch(
populateZidMetadataStore(this.props.match.params.conversation_id)
)

if (zid_metadata.is_mod) {
// If we already have is_mod, get the data
if (zid_metadata?.is_mod) {
this.getData()
}
}

componentDidUpdate() {
const { zid_metadata } = this.props
if (zid_metadata?.is_mod) {
this.getData()
}
}
Expand Down Expand Up @@ -75,7 +89,7 @@ class ReportsList extends React.Component {
</Box>
{this.state.reports.map((report) => {
return (
<Box sx={{ mb: [2] }} key={report.report_id}>
<Box sx={{ mb: [2] }} key={report.report_id} data-test-id="report-list-item">
<a
target="_blank"
rel="noreferrer"
Expand Down
15 changes: 13 additions & 2 deletions client-admin/src/components/conversation-admin/stats/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import dateSetupUtil from '../../../util/data-export-date-setup'
import React from 'react'
import { connect } from 'react-redux'
import { populateConversationStatsStore } from '../../../actions'
import { populateConversationStatsStore, populateZidMetadataStore } from '../../../actions'
import NumberCards from './conversation-stats-number-cards'
import Voters from './voters'
import Commenters from './commenters'
Expand Down Expand Up @@ -52,7 +52,11 @@ class ConversationStats extends React.Component {
}

componentDidMount() {
const { zid_metadata } = this.props
const { zid_metadata, match } = this.props

this.props.dispatch(
populateZidMetadataStore(match.params.conversation_id)
)

if (zid_metadata.is_mod) {
this.loadStats()
Expand All @@ -62,6 +66,13 @@ class ConversationStats extends React.Component {
}
}

componentDidUpdate() {
const { zid_metadata } = this.props
if (zid_metadata?.is_mod) {
this.loadStats()
}
}

componentWillUnmount() {
const { zid_metadata } = this.props

Expand Down
8 changes: 4 additions & 4 deletions client-report/src/components/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -447,29 +447,29 @@ class App extends React.Component {
render() {
if (this.state.error) {
return (
<div>
<div data-testid="reports-overview">
<div> Error Loading </div>
<div> {this.state.errorText} </div>
</div>
);
}
if (this.state.nothingToShow) {
return (
<div>
<div data-testid="reports-overview">
<div> Nothing to show yet </div>
</div>
);
}
if (this.state.loading) {
return (
<div>
<div data-testid="reports-overview">
<div> Loading ... </div>
</div>
);
}
console.log("top level app state and props", this.state, this.props);
return (
<div style={{ margin: "0px 10px" }}>
<div style={{ margin: "0px 10px" }} data-testid="reports-overview">
<Heading conversation={this.state.conversation} />
<div
style={{
Expand Down
53 changes: 53 additions & 0 deletions e2e/cypress/e2e/client-admin/comment-moderation.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
describe('Comment Moderation', function () {
beforeEach(function () {
cy.intercept('GET', '/api/v3/conversations*').as('getConversations')
cy.intercept('GET', '/api/v3/comments*').as('getComments')
cy.intercept('POST', '/api/v3/comments').as('createComment')
cy.intercept('PUT', '/api/v3/comments*').as('updateComment')
cy.intercept('PUT', '/api/v3/mod/comments*').as('moderateComment')

// Create a conversation and add some comments
cy.createConvo().then(() => {
cy.visit('/m/' + this.convoId)
cy.wait('@getConversations')

// Set up initial comments
cy.get('textarea[data-test-id="seed_form"]').type('Initial comment for moderation')
cy.get('button').contains('Submit').click()
cy.wait('@createComment')
})
})

describe('Basic Moderation Actions', function () {
it('should reject an approved comment', function () {
cy.get('[data-test-id="moderate-comments"]').click()
cy.get('[data-test-id="filter-approved"]').click()
cy.get('[data-test-id="reject-comment"]').click()
cy.wait('@updateComment').then(({ response }) => {
expect(response.statusCode).to.equal(200)
})
cy.get('[data-test-id="pending-comment"]').should('not.exist')
cy.get('[data-test-id="filter-rejected"]').click()
cy.contains('button', 'accept').click()
cy.wait('@updateComment').then(({ response }) => {
expect(response.statusCode).to.equal(200)
})
})
})

describe('Moderation Settings', function () {
it('should filter comments by moderation status', function () {
cy.get('[data-test-id="moderate-comments"]').click()

// Test different filter options
cy.get('[data-test-id="filter-approved"]').click()
cy.get('[data-test-id="approved-comments"]').should('be.visible')

cy.get('[data-test-id="filter-rejected"]').click()
cy.get('[data-test-id="rejected-comments"]').should('exist')

cy.get('[data-test-id="mod-queue"]').click()
cy.get('[data-test-id="pending-comment"]').should('exist')
})
})
})
86 changes: 75 additions & 11 deletions e2e/cypress/e2e/client-admin/conversation.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,29 +38,25 @@ describe('Conversation: Configure', function () {
cy.contains('button', 'Create new conversation').click()

cy.wait('@createConversation').then(({ response }) =>
cy.location('pathname').should('eq', '/m/' + response.body.conversation_id)
cy.location('pathname').should('eq', '/m/' + response.body.conversation_id),
)

cy.contains('h3', 'Configure').should('be.visible')

cy.get('input[data-test-id="topic"]')
.type('Test topic')
cy.get('input[data-test-id="topic"]').type('Test topic')

cy.get('input[data-test-id="topic"]')
.then(() => cy.focused().blur())
cy.get('input[data-test-id="topic"]').then(() => cy.focused().blur())

cy.wait('@updateConversation').then(({ response }) =>
expect(response.body.topic).to.equal('Test topic')
expect(response.body.topic).to.equal('Test topic'),
)

cy.get('textarea[data-test-id="description"]')
.type('Test description')
cy.get('textarea[data-test-id="description"]').type('Test description')

cy.get('textarea[data-test-id="description"]')
.then(() => cy.focused().blur())
cy.get('textarea[data-test-id="description"]').then(() => cy.focused().blur())

cy.wait('@updateConversation').then(({ response }) =>
expect(response.body.description).to.equal('Test description')
expect(response.body.description).to.equal('Test description'),
)

cy.get('textarea[data-test-id="seed_form"]').type('Test seed comment')
Expand All @@ -72,6 +68,74 @@ describe('Conversation: Configure', function () {
})
})

describe('Conversation Participation', function () {
beforeEach(function () {
cy.createConvo().then(() => {
cy.visit('/m/' + this.convoId)
cy.wait('@getConversations')
cy.get('input[data-test-id="topic"]').type('Participation Test Topic')
cy.get('textarea[data-test-id="description"]').type('Test description')
cy.get('textarea[data-test-id="seed_form"]').type('Initial seed comment')
cy.get('button').contains('Submit').click()
})
})

it('should allow multiple seed comments', function () {
cy.wait('@createComment', { timeout: 7000 })
cy.get('textarea[data-test-id="seed_form"]').clear()
cy.get('textarea[data-test-id="seed_form"]').type('Second seed comment')
// pause for 1 second to ensure the button is in correct state
cy.pause()

cy.get('button').contains('Submit').click()
cy.wait('@createComment', { timeout: 7000 })
cy.get('textarea[data-test-id="seed_form"]').clear()
cy.get('textarea[data-test-id="seed_form"]').type('third seed comment')
// pause for 1 second to ensure the button is in correct state
cy.pause()

cy.get('button').contains('Submit').click()
cy.wait('@createComment', { timeout: 7000 })

// Verify all seed comments are visible by checking API response
cy.request(`/api/v3/comments?conversation_id=${this.convoId}`).then((response) =>
expect(response.body.length).to.equal(3),
)
})

it('should handle special characters in topic and description', function () {
const specialTopic = 'Test & Topic with $pecial <characters>'
const specialDesc = '!@#$%^&*() Special description 你好'

cy.get('input[data-test-id="topic"]').clear().type(specialTopic)
cy.get('input[data-test-id="topic"]').then(() => cy.focused().blur())
cy.wait('@updateConversation')

cy.get('textarea[data-test-id="description"]').clear().type(specialDesc)
cy.get('textarea[data-test-id="description"]').then(() => cy.focused().blur())
cy.wait('@updateConversation')

// Verify the content is saved correctly
cy.reload()
cy.get('input[data-test-id="topic"]').should('have.value', specialTopic)
cy.get('textarea[data-test-id="description"]').should('have.value', specialDesc)
})
})

describe('Conversation Settings', function () {
beforeEach(function () {
cy.createConvo().then(() => cy.visit('/m/' + this.convoId))
cy.wait('@getConversations')
})

it('should toggle visibility settings correctly', function () {
cy.get('input[data-test-id="vis_type"]').check()
cy.wait('@updateConversation').then(({ response }) => {
expect(response.body.is_public).to.be.true
})
})
})

describe('Closing a Conversation', function () {
beforeEach(function () {
cy.createConvo().then(() => cy.visit('/m/' + this.convoId))
Expand Down
Loading
Loading