259 lines
6.5 KiB
TypeScript
259 lines
6.5 KiB
TypeScript
import { h } from 'preact';
|
|
import '@testing-library/jest-dom';
|
|
import { fireEvent, screen, waitFor } from '@testing-library/preact';
|
|
import { useIntl, IntlShape } from 'react-intl';
|
|
|
|
import { render } from 'tests/utils';
|
|
import { StaticStore } from 'common/static-store';
|
|
|
|
import { Comment, CommentProps } from './comment';
|
|
import { CommentMode } from 'common/types';
|
|
|
|
function CommentWithIntl(props: CommentProps) {
|
|
const intl = useIntl();
|
|
|
|
return <Comment {...props} intl={intl} />;
|
|
}
|
|
|
|
function getProps(): CommentProps {
|
|
return {
|
|
isCommentsDisabled: false,
|
|
theme: 'light',
|
|
post_info: {
|
|
url: 'http://localhost/post/1',
|
|
count: 2,
|
|
read_only: false,
|
|
},
|
|
view: 'main',
|
|
data: {
|
|
id: 'comment_id',
|
|
text: 'test comment',
|
|
vote: 0,
|
|
time: new Date().toString(),
|
|
pid: 'parent_id',
|
|
score: 0,
|
|
voted_ips: [],
|
|
locator: {
|
|
url: 'somelocatorurl',
|
|
site: 'remark',
|
|
},
|
|
user: {
|
|
id: 'someone',
|
|
picture: 'http://localhost/somepicture-url',
|
|
name: 'username',
|
|
ip: '',
|
|
admin: false,
|
|
block: false,
|
|
verified: false,
|
|
},
|
|
},
|
|
user: {
|
|
id: 'testuser',
|
|
picture: 'http://localhost/testuser-url',
|
|
name: 'test',
|
|
ip: '',
|
|
admin: false,
|
|
block: false,
|
|
verified: false,
|
|
},
|
|
intl: {} as IntlShape,
|
|
};
|
|
}
|
|
|
|
describe('<Comment />', () => {
|
|
let props = getProps();
|
|
|
|
beforeEach(() => {
|
|
props = getProps();
|
|
});
|
|
|
|
it('should render patreon subscriber icon', async () => {
|
|
const props = getProps();
|
|
props.data.user.paid_sub = true;
|
|
|
|
render(<CommentWithIntl {...props} />);
|
|
const patreonSubscriberIcon = await screen.findByAltText('Patreon Paid Subscriber');
|
|
expect(patreonSubscriberIcon).toBeVisible();
|
|
expect(patreonSubscriberIcon.tagName).toBe('IMG');
|
|
});
|
|
|
|
describe('verification', () => {
|
|
it('should render active verification icon', () => {
|
|
props.data.user.verified = true;
|
|
render(<CommentWithIntl {...props} />);
|
|
expect(screen.getByTitle('Verified user')).toBeVisible();
|
|
});
|
|
|
|
it('should not render verification icon', () => {
|
|
const props = getProps();
|
|
render(<CommentWithIntl {...props} />);
|
|
expect(screen.queryByTitle('Verified user')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('should render verification button for admin', () => {
|
|
props.user!.admin = true;
|
|
render(<CommentWithIntl {...props} />);
|
|
expect(screen.getByTitle('Toggle verification')).toBeVisible();
|
|
});
|
|
|
|
it('should render active verification icon for admin', () => {
|
|
props.user!.admin = true;
|
|
props.data.user.verified = true;
|
|
render(<CommentWithIntl {...props} />);
|
|
expect(screen.queryByTitle('Verified user')).toBeVisible();
|
|
});
|
|
});
|
|
|
|
describe('voting', () => {
|
|
let props = getProps();
|
|
|
|
beforeEach(() => {
|
|
props = getProps();
|
|
});
|
|
|
|
it('should render vote component', () => {
|
|
render(<CommentWithIntl {...props} />);
|
|
expect(screen.getByTitle('Votes score')).toBeVisible();
|
|
});
|
|
it.each([
|
|
[
|
|
'when the comment is pinned',
|
|
() => {
|
|
props.view = 'pinned';
|
|
},
|
|
],
|
|
[
|
|
'when rendered in profile',
|
|
() => {
|
|
props.view = 'user';
|
|
},
|
|
],
|
|
[
|
|
'when rendered in preview',
|
|
() => {
|
|
props.view = 'preview';
|
|
},
|
|
],
|
|
[
|
|
'when post is read only',
|
|
() => {
|
|
props.post_info!.read_only = true;
|
|
},
|
|
],
|
|
[
|
|
'when comment was deleted',
|
|
() => {
|
|
props.data.delete = true;
|
|
},
|
|
],
|
|
[
|
|
'on current user comments',
|
|
() => {
|
|
props.user!.id = 'testuser';
|
|
props.data.user.id = 'testuser';
|
|
},
|
|
],
|
|
[
|
|
'for guest users',
|
|
() => {
|
|
props.user = null;
|
|
},
|
|
],
|
|
[
|
|
'for anonymous users',
|
|
() => {
|
|
props.user!.id = 'anonymous_1';
|
|
},
|
|
],
|
|
])('should not render vote component %s', (_, action) => {
|
|
action();
|
|
render(<CommentWithIntl {...props} />);
|
|
expect(screen.queryByText('Votes score')).not.toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it('should render action buttons', () => {
|
|
render(<CommentWithIntl {...props} />);
|
|
expect(screen.getByText('Reply')).toBeVisible();
|
|
});
|
|
|
|
it.each([
|
|
[
|
|
'pinned',
|
|
() => {
|
|
props.view = 'pinned';
|
|
},
|
|
],
|
|
[
|
|
'deleted',
|
|
() => {
|
|
props.data.delete = true;
|
|
},
|
|
],
|
|
[
|
|
'collapsed',
|
|
() => {
|
|
props.collapsed = true;
|
|
},
|
|
],
|
|
])('should not render actions when comment is %s', (_, mutateProps) => {
|
|
mutateProps();
|
|
render(<CommentWithIntl {...props} />);
|
|
expect(screen.queryByTitle('Reply')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('should be editable', async () => {
|
|
StaticStore.config.edit_duration = 300;
|
|
|
|
props.repliesCount = 0;
|
|
props.user!.id = '100';
|
|
props.data.user.id = '100';
|
|
Object.assign(props.data, {
|
|
id: '101',
|
|
vote: 1,
|
|
time: Date.now(),
|
|
delete: false,
|
|
orig: 'test',
|
|
});
|
|
|
|
render(<CommentWithIntl {...props} />);
|
|
expect(screen.getByText('Edit')).toBeVisible();
|
|
});
|
|
|
|
it('should not be editable', () => {
|
|
StaticStore.config.edit_duration = 300;
|
|
Object.assign(props.data, {
|
|
user: props.user,
|
|
id: '100',
|
|
vote: 1,
|
|
time: new Date(new Date().getDate() - 300).toString(),
|
|
orig: 'test',
|
|
});
|
|
|
|
render(<CommentWithIntl {...props} />);
|
|
expect(screen.queryByRole('timer')).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('toggles edit mode', async () => {
|
|
props = getProps();
|
|
props.repliesCount = 0;
|
|
props.data.user = props.user!;
|
|
props.data.time = new Date().toString();
|
|
props.setReplyEditState = jest.fn().mockImplementation(() => {
|
|
props.editMode = props.editMode === undefined ? CommentMode.Edit : CommentMode.None;
|
|
});
|
|
StaticStore.config.edit_duration = 300;
|
|
const { rerender } = render(<CommentWithIntl {...props} />);
|
|
fireEvent(screen.getByText('Edit'), new MouseEvent('click', { bubbles: true }));
|
|
rerender(<CommentWithIntl {...props} />);
|
|
await waitFor(() => {
|
|
expect(screen.getByText('Cancel')).toBeVisible();
|
|
});
|
|
fireEvent(screen.getByText('Cancel'), new MouseEvent('click', { bubbles: true }));
|
|
rerender(<CommentWithIntl {...props} />);
|
|
await waitFor(() => {
|
|
expect(screen.getByText('Edit')).toBeVisible();
|
|
});
|
|
});
|
|
});
|