mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-30 22:34:01 -05:00
✨ Improved various aspects of comments app
ref https://linear.app/ghost/issue/PLG-300/ Full details available soon on https://ghost.org/changelog/ - removed `commentImprovements` labs flag conditionals
This commit is contained in:
parent
904a30082e
commit
3dd33968f5
87 changed files with 1205 additions and 1847 deletions
|
@ -7,7 +7,7 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react';
|
|||
import i18nLib from '@tryghost/i18n';
|
||||
import setupGhostApi from './utils/api';
|
||||
import {ActionHandler, SyncActionHandler, isSyncAction} from './actions';
|
||||
import {AppContext, DispatchActionType, EditableAppContext, LabsContextType} from './AppContext';
|
||||
import {AppContext, DispatchActionType, EditableAppContext} from './AppContext';
|
||||
import {CommentsFrame} from './components/Frame';
|
||||
import {setupAdminAPI} from './utils/adminApi';
|
||||
import {useOptions} from './utils/options';
|
||||
|
@ -44,8 +44,6 @@ const App: React.FC<AppProps> = ({scriptTag}) => {
|
|||
});
|
||||
}, [options]);
|
||||
|
||||
// const [adminApi, setAdminApi] = useState<AdminApi|null>(null);
|
||||
|
||||
const setState = useCallback((newState: Partial<EditableAppContext> | ((state: EditableAppContext) => Partial<EditableAppContext>)) => {
|
||||
setFullState((state) => {
|
||||
if (typeof newState === 'function') {
|
||||
|
@ -114,7 +112,7 @@ const App: React.FC<AppProps> = ({scriptTag}) => {
|
|||
let admin = null;
|
||||
try {
|
||||
admin = await adminApi.getUser();
|
||||
if (admin && state.labs.commentImprovements) {
|
||||
if (admin) {
|
||||
// this is a bit of a hack, but we need to fetch the comments fully populated if the user is an admin
|
||||
const adminComments = await adminApi.browse({page: 1, postId: options.postId, order: state.order, memberUuid: state.member?.uuid});
|
||||
setState({
|
||||
|
@ -141,14 +139,8 @@ const App: React.FC<AppProps> = ({scriptTag}) => {
|
|||
};
|
||||
|
||||
/** Fetch first few comments */
|
||||
const fetchComments = async (labs: LabsContextType) => {
|
||||
let dataPromise;
|
||||
if (labs?.commentImprovements) {
|
||||
dataPromise = api.comments.browse({page: 1, postId: options.postId, order: state.order});
|
||||
} else {
|
||||
dataPromise = api.comments.browse({page: 1, postId: options.postId});
|
||||
}
|
||||
|
||||
const fetchComments = async () => {
|
||||
const dataPromise = api.comments.browse({page: 1, postId: options.postId, order: state.order});
|
||||
const countPromise = api.comments.count({postId: options.postId});
|
||||
|
||||
const [data, count] = await Promise.all([dataPromise, countPromise]);
|
||||
|
@ -165,15 +157,14 @@ const App: React.FC<AppProps> = ({scriptTag}) => {
|
|||
try {
|
||||
// Fetch data from API, links, preview, dev sources
|
||||
const {member, labs} = await api.init();
|
||||
const {comments, pagination, count} = await fetchComments(labs);
|
||||
const order = labs.commentImprovements ? 'count__likes desc, created_at desc' : 'created_at desc';
|
||||
const {comments, pagination, count} = await fetchComments();
|
||||
const state = {
|
||||
member,
|
||||
initStatus: 'success',
|
||||
comments,
|
||||
pagination,
|
||||
commentCount: count,
|
||||
order,
|
||||
order: 'count__likes desc, created_at desc',
|
||||
labs: labs,
|
||||
commentsIsLoading: false,
|
||||
commentIdToHighlight: null
|
||||
|
|
|
@ -9,7 +9,7 @@ async function loadMoreComments({state, api, options, order}: {state: EditableAp
|
|||
page = state.pagination.page + 1;
|
||||
}
|
||||
let data;
|
||||
if (state.admin && state.adminApi && state.labs.commentImprovements) {
|
||||
if (state.admin && state.adminApi) {
|
||||
data = await state.adminApi.browse({page, postId: options.postId, order: order || state.order, memberUuid: state.member?.uuid});
|
||||
} else {
|
||||
data = await api.comments.browse({page, postId: options.postId, order: order || state.order});
|
||||
|
@ -33,7 +33,7 @@ async function setOrder({state, data: {order}, options, api, dispatchAction}: {s
|
|||
|
||||
try {
|
||||
let data;
|
||||
if (state.admin && state.adminApi && state.labs.commentImprovements) {
|
||||
if (state.admin && state.adminApi) {
|
||||
data = await state.adminApi.browse({page: 1, postId: options.postId, order, memberUuid: state.member?.uuid});
|
||||
} else {
|
||||
data = await api.comments.browse({page: 1, postId: options.postId, order});
|
||||
|
@ -54,7 +54,7 @@ async function setOrder({state, data: {order}, options, api, dispatchAction}: {s
|
|||
|
||||
async function loadMoreReplies({state, api, data: {comment, limit}, isReply}: {state: EditableAppContext, api: GhostApi, data: {comment: any, limit?: number | 'all'}, isReply: boolean}): Promise<Partial<EditableAppContext>> {
|
||||
let data;
|
||||
if (state.admin && state.adminApi && state.labs.commentImprovements && !isReply) { // we don't want the admin api to load reply data for replying to a reply, so we pass isReply: true
|
||||
if (state.admin && state.adminApi && !isReply) { // we don't want the admin api to load reply data for replying to a reply, so we pass isReply: true
|
||||
data = await state.adminApi.replies({commentId: comment.id, afterReplyId: comment.replies[comment.replies.length - 1]?.id, limit, memberUuid: state.member?.uuid});
|
||||
} else {
|
||||
data = await api.comments.replies({commentId: comment.id, afterReplyId: comment.replies[comment.replies.length - 1]?.id, limit});
|
||||
|
@ -155,7 +155,7 @@ async function showComment({state, api, data: comment}: {state: EditableAppConte
|
|||
// We need to refetch the comment, to make sure we have an up to date HTML content
|
||||
// + all relations are loaded as the current member (not the admin)
|
||||
let data;
|
||||
if (state.admin && state.adminApi && state.labs.commentImprovements) {
|
||||
if (state.admin && state.adminApi) {
|
||||
data = await state.adminApi.read({commentId: comment.id, memberUuid: state.member?.uuid});
|
||||
} else {
|
||||
data = await api.comments.read(comment.id);
|
||||
|
@ -279,60 +279,29 @@ async function deleteComment({state, api, data: comment}: {state: EditableAppCon
|
|||
}
|
||||
});
|
||||
|
||||
if (state.labs.commentImprovements) {
|
||||
return {
|
||||
comments: state.comments.map((c) => {
|
||||
// If the comment has replies we want to keep it so the replies are
|
||||
// still visible, but mark the comment as deleted. Otherwise remove it.
|
||||
if (c.id === comment.id) {
|
||||
if (c.replies.length > 0) {
|
||||
return {
|
||||
...c,
|
||||
status: 'deleted'
|
||||
};
|
||||
} else {
|
||||
return null; // Will be filtered out later
|
||||
}
|
||||
}
|
||||
|
||||
const updatedReplies = c.replies.filter(r => r.id !== comment.id);
|
||||
return {
|
||||
...c,
|
||||
replies: updatedReplies
|
||||
};
|
||||
}).filter(Boolean),
|
||||
commentCount: state.commentCount - 1
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
comments: state.comments.map((c) => {
|
||||
const replies = c.replies.map((r) => {
|
||||
if (r.id === comment.id) {
|
||||
return {
|
||||
...r,
|
||||
status: 'deleted'
|
||||
};
|
||||
}
|
||||
|
||||
return r;
|
||||
});
|
||||
|
||||
if (c.id === comment.id) {
|
||||
return {
|
||||
comments: state.comments.map((c) => {
|
||||
// If the comment has replies we want to keep it so the replies are
|
||||
// still visible, but mark the comment as deleted. Otherwise remove it.
|
||||
if (c.id === comment.id) {
|
||||
if (c.replies.length > 0) {
|
||||
return {
|
||||
...c,
|
||||
status: 'deleted',
|
||||
replies
|
||||
status: 'deleted'
|
||||
};
|
||||
} else {
|
||||
return null; // Will be filtered out later
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...c,
|
||||
replies
|
||||
};
|
||||
}),
|
||||
commentCount: state.commentCount - 1
|
||||
};
|
||||
}
|
||||
const updatedReplies = c.replies.filter(r => r.id !== comment.id);
|
||||
return {
|
||||
...c,
|
||||
replies: updatedReplies
|
||||
};
|
||||
}).filter(Boolean),
|
||||
commentCount: state.commentCount - 1
|
||||
};
|
||||
}
|
||||
|
||||
async function editComment({state, api, data: {comment, parent}}: {state: EditableAppContext, api: GhostApi, data: {comment: Partial<Comment> & {id: string}, parent?: Comment}}) {
|
||||
|
|
|
@ -32,7 +32,7 @@ describe('<CommentComponent>', function () {
|
|||
const parent = buildComment({
|
||||
replies: [reply1, reply2]
|
||||
});
|
||||
const appContext = {comments: [parent], labs: {commentImprovements: true}};
|
||||
const appContext = {comments: [parent]};
|
||||
|
||||
contextualRender(<CommentComponent comment={reply2} parent={parent} />, {appContext});
|
||||
|
||||
|
@ -53,7 +53,7 @@ describe('<RepliedToSnippet>', function () {
|
|||
const parent = buildComment({
|
||||
replies: [reply1, reply2]
|
||||
});
|
||||
const appContext = {comments: [parent], labs: {commentImprovements: true}};
|
||||
const appContext = {comments: [parent]};
|
||||
|
||||
contextualRender(<RepliedToSnippet comment={reply2} />, {appContext});
|
||||
|
||||
|
@ -74,7 +74,7 @@ describe('<RepliedToSnippet>', function () {
|
|||
const parent = buildComment({
|
||||
replies: [reply1, reply2]
|
||||
});
|
||||
const appContext = {comments: [parent], labs: {commentImprovements: true}};
|
||||
const appContext = {comments: [parent]};
|
||||
|
||||
contextualRender(<RepliedToSnippet comment={reply2} />, {appContext});
|
||||
|
||||
|
@ -91,7 +91,7 @@ describe('<RepliedToSnippet>', function () {
|
|||
const parent = buildComment({
|
||||
replies: [reply2]
|
||||
});
|
||||
const appContext = {comments: [parent], labs: {commentImprovements: true}};
|
||||
const appContext = {comments: [parent]};
|
||||
|
||||
contextualRender(<RepliedToSnippet comment={reply2} />, {appContext});
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import Replies, {RepliesProps} from './Replies';
|
|||
import ReplyButton from './buttons/ReplyButton';
|
||||
import ReplyForm from './forms/ReplyForm';
|
||||
import {Avatar, BlankAvatar} from './Avatar';
|
||||
import {Comment, OpenCommentForm, useAppContext, useLabs} from '../../AppContext';
|
||||
import {Comment, OpenCommentForm, useAppContext} from '../../AppContext';
|
||||
import {Transition} from '@headlessui/react';
|
||||
import {findCommentById, formatExplicitTime, getCommentInReplyToSnippet, getMemberNameFromComment} from '../../utils/helpers';
|
||||
import {useCallback} from 'react';
|
||||
|
@ -39,8 +39,7 @@ const AnimatedComment: React.FC<AnimatedCommentProps> = ({comment, parent}) => {
|
|||
|
||||
export const CommentComponent: React.FC<CommentProps> = ({comment, parent}) => {
|
||||
const {dispatchAction, admin} = useAppContext();
|
||||
const labs = useLabs();
|
||||
const {showDeletedMessage, showHiddenMessage, showCommentContent} = useCommentVisibility(comment, admin, labs);
|
||||
const {showDeletedMessage, showHiddenMessage, showCommentContent} = useCommentVisibility(comment, admin);
|
||||
|
||||
const openEditMode = useCallback(() => {
|
||||
const newForm: OpenCommentForm = {
|
||||
|
@ -53,39 +52,28 @@ export const CommentComponent: React.FC<CommentProps> = ({comment, parent}) => {
|
|||
dispatchAction('openCommentForm', newForm);
|
||||
}, [comment.id, dispatchAction]);
|
||||
|
||||
if (showDeletedMessage) {
|
||||
if (showDeletedMessage || showHiddenMessage) {
|
||||
return <UnpublishedComment comment={comment} openEditMode={openEditMode} />;
|
||||
} else if (showCommentContent && !showHiddenMessage) {
|
||||
return <PublishedComment comment={comment} openEditMode={openEditMode} parent={parent} />;
|
||||
} else if (!labs.commentImprovements && comment.status !== 'published' || showHiddenMessage) {
|
||||
return <UnpublishedComment comment={comment} openEditMode={openEditMode} />;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
type CommentProps = AnimatedCommentProps;
|
||||
const useCommentVisibility = (comment: Comment, admin: boolean, labs: {commentImprovements?: boolean}) => {
|
||||
const useCommentVisibility = (comment: Comment, admin: boolean) => {
|
||||
const hasReplies = comment.replies && comment.replies.length > 0;
|
||||
const isDeleted = comment.status === 'deleted';
|
||||
const isHidden = comment.status === 'hidden';
|
||||
|
||||
if (labs?.commentImprovements) {
|
||||
return {
|
||||
// Show deleted message only when comment has replies (regardless of admin status)
|
||||
showDeletedMessage: isDeleted && hasReplies,
|
||||
// Show hidden message for non-admins when comment has replies
|
||||
showHiddenMessage: hasReplies && isHidden && !admin,
|
||||
// Show comment content if not deleted AND (is published OR admin viewing hidden)
|
||||
showCommentContent: !isDeleted && (admin || comment.status === 'published')
|
||||
};
|
||||
}
|
||||
|
||||
// Original behavior when labs is false
|
||||
return {
|
||||
showDeletedMessage: false,
|
||||
showHiddenMessage: false,
|
||||
showCommentContent: comment.status === 'published'
|
||||
// Show deleted message only when comment has replies (regardless of admin status)
|
||||
showDeletedMessage: isDeleted && hasReplies,
|
||||
// Show hidden message for non-admins when comment has replies
|
||||
showHiddenMessage: hasReplies && isHidden && !admin,
|
||||
// Show comment content if not deleted AND (is published OR admin viewing hidden)
|
||||
showCommentContent: !isDeleted && (admin || comment.status === 'published')
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -94,10 +82,9 @@ type PublishedCommentProps = CommentProps & {
|
|||
}
|
||||
const PublishedComment: React.FC<PublishedCommentProps> = ({comment, parent, openEditMode}) => {
|
||||
const {dispatchAction, openCommentForms, admin, commentIdToHighlight} = useAppContext();
|
||||
const labs = useLabs();
|
||||
|
||||
// Determine if the comment should be displayed with reduced opacity
|
||||
const isHidden = labs.commentImprovements && admin && comment.status === 'hidden';
|
||||
const isHidden = admin && comment.status === 'hidden';
|
||||
const hiddenClass = isHidden ? 'opacity-30' : '';
|
||||
|
||||
// Check if this comment is being edited
|
||||
|
@ -171,11 +158,11 @@ type UnpublishedCommentProps = {
|
|||
openEditMode: () => void;
|
||||
}
|
||||
const UnpublishedComment: React.FC<UnpublishedCommentProps> = ({comment, openEditMode}) => {
|
||||
const {openCommentForms, t, labs, admin} = useAppContext();
|
||||
const {admin, openCommentForms, t} = useAppContext();
|
||||
|
||||
const avatar = (labs.commentImprovements && admin && comment.status !== 'deleted') ?
|
||||
<Avatar comment={comment} /> :
|
||||
<BlankAvatar />;
|
||||
const avatar = (admin && comment.status !== 'deleted')
|
||||
? <Avatar comment={comment} />
|
||||
: <BlankAvatar />;
|
||||
const hasReplies = comment.replies && comment.replies.length > 0;
|
||||
|
||||
const notPublishedMessage = comment.status === 'hidden' ?
|
||||
|
@ -322,10 +309,9 @@ type CommentHeaderProps = {
|
|||
|
||||
const CommentHeader: React.FC<CommentHeaderProps> = ({comment, className = ''}) => {
|
||||
const {member, t} = useAppContext();
|
||||
const labs = useLabs();
|
||||
const createdAtRelative = useRelativeTime(comment.created_at);
|
||||
const memberExpertise = member && comment.member && comment.member.uuid === member.uuid ? member.expertise : comment?.member?.expertise;
|
||||
const isReplyToReply = labs.commentImprovements && comment.in_reply_to_id && comment.in_reply_to_snippet;
|
||||
const isReplyToReply = comment.in_reply_to_id && comment.in_reply_to_snippet;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -395,39 +381,25 @@ type CommentMenuProps = {
|
|||
parent?: Comment;
|
||||
className?: string;
|
||||
};
|
||||
const CommentMenu: React.FC<CommentMenuProps> = ({comment, openReplyForm, highlightReplyButton, openEditMode, parent, className = ''}) => {
|
||||
const {member, commentsEnabled, t, admin} = useAppContext();
|
||||
const labs = useLabs();
|
||||
const CommentMenu: React.FC<CommentMenuProps> = ({comment, openReplyForm, highlightReplyButton, openEditMode, className = ''}) => {
|
||||
const {admin, t} = useAppContext();
|
||||
|
||||
const paidOnly = commentsEnabled === 'paid';
|
||||
const isPaidMember = member && !!member.paid;
|
||||
const canReply = member && (isPaidMember || !paidOnly) && (labs.commentImprovements ? true : !parent);
|
||||
const isHiddenForAdmin = labs.commentImprovements && admin && comment.status === 'hidden';
|
||||
|
||||
if (isHiddenForAdmin) {
|
||||
if (admin && comment.status === 'hidden') {
|
||||
return (
|
||||
<div className={`flex items-center gap-4 ${className}`}>
|
||||
<span className="font-sans text-base leading-snug text-red-600 sm:text-sm">{t('Hidden for members')}</span>
|
||||
{<MoreButton comment={comment} toggleEdit={openEditMode} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
labs.commentImprovements ? (
|
||||
} else {
|
||||
return (
|
||||
<div className={`flex items-center gap-4 ${className}`}>
|
||||
{<LikeButton comment={comment} />}
|
||||
{<ReplyButton isReplying={highlightReplyButton} openReplyForm={openReplyForm} />}
|
||||
{<MoreButton comment={comment} toggleEdit={openEditMode} />}
|
||||
</div>
|
||||
) : (
|
||||
<div className={`flex items-center gap-4 ${className}`}>
|
||||
{<LikeButton comment={comment} />}
|
||||
{(canReply && <ReplyButton isReplying={highlightReplyButton} openReplyForm={openReplyForm} />)}
|
||||
{<MoreButton comment={comment} toggleEdit={openEditMode} />}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
@ -44,10 +44,10 @@ describe('<Content>', function () {
|
|||
expect(screen.queryByTestId('main-form')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders no CTA or form when a reply form is open', function () {
|
||||
it('renders main form when a reply form is open', function () {
|
||||
contextualRender(<Content />, {appContext: {member: {}, openFormCount: 1}});
|
||||
expect(screen.queryByTestId('cta-box')).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId('main-form')).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId('main-form')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,16 +10,7 @@ import {useEffect} from 'react';
|
|||
|
||||
const Content = () => {
|
||||
const labs = useLabs();
|
||||
const {pagination, member, comments, commentCount, commentsEnabled, title, showCount, openFormCount, commentsIsLoading, t} = useAppContext();
|
||||
|
||||
let commentsElements;
|
||||
const commentsDataset = comments;
|
||||
|
||||
if (labs && labs.commentImprovements) {
|
||||
commentsElements = commentsDataset.slice().map(comment => <Comment key={comment.id} comment={comment} />);
|
||||
} else {
|
||||
commentsElements = commentsDataset.slice().reverse().map(comment => <Comment key={comment.id} comment={comment} />);
|
||||
}
|
||||
const {pagination, member, comments, commentCount, commentsEnabled, title, showCount, commentsIsLoading, t} = useAppContext();
|
||||
|
||||
useEffect(() => {
|
||||
const elem = document.getElementById(ROOT_DIV_ID);
|
||||
|
@ -42,60 +33,36 @@ const Content = () => {
|
|||
const isPaidOnly = commentsEnabled === 'paid';
|
||||
const isPaidMember = member && !!member.paid;
|
||||
const isFirst = pagination?.total === 0;
|
||||
const hasOpenReplyForms = openFormCount > 0;
|
||||
|
||||
const commentsComponents = comments.slice().map(comment => <Comment key={comment.id} comment={comment} />);
|
||||
|
||||
return (
|
||||
labs.commentImprovements ? (
|
||||
<>
|
||||
<ContentTitle count={commentCount} showCount={showCount} title={title}/>
|
||||
<div>
|
||||
{(member && (isPaidMember || !isPaidOnly)) ? (
|
||||
<MainForm commentsCount={comments.length} />
|
||||
) : (
|
||||
<section className="flex flex-col items-center py-6 sm:px-8 sm:py-10" data-testid="cta-box">
|
||||
<CTABox isFirst={isFirst} isPaid={isPaidOnly} />
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
{commentCount > 1 && (
|
||||
<div className="z-20 mb-7 mt-3">
|
||||
<span className="flex items-center gap-1.5 text-sm font-medium text-neutral-900 dark:text-neutral-100">
|
||||
{t('Sort by')}: <SortingForm/>
|
||||
</span>
|
||||
</div>
|
||||
<>
|
||||
<ContentTitle count={commentCount} showCount={showCount} title={title}/>
|
||||
<div>
|
||||
{(member && (isPaidMember || !isPaidOnly)) ? (
|
||||
<MainForm commentsCount={comments.length} />
|
||||
) : (
|
||||
<section className="flex flex-col items-center py-6 sm:px-8 sm:py-10" data-testid="cta-box">
|
||||
<CTABox isFirst={isFirst} isPaid={isPaidOnly} />
|
||||
</section>
|
||||
)}
|
||||
<div className={`z-10 transition-opacity duration-100 ${commentsIsLoading ? 'opacity-50' : ''}`} data-testid="comment-elements">
|
||||
{commentsElements}
|
||||
</div>
|
||||
{commentCount > 1 && (
|
||||
<div className="z-20 mb-7 mt-3">
|
||||
<span className="flex items-center gap-1.5 text-sm font-medium text-neutral-900 dark:text-neutral-100">
|
||||
{t('Sort by')}: <SortingForm/>
|
||||
</span>
|
||||
</div>
|
||||
<Pagination />
|
||||
{
|
||||
labs?.testFlag ? <div data-testid="this-comes-from-a-flag" style={{display: 'none'}}></div> : null
|
||||
}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<ContentTitle count={commentCount} showCount={showCount} title={title}/>
|
||||
<Pagination />
|
||||
<div className={!pagination ? 'mt-4' : ''} data-testid="comment-elements">
|
||||
{commentsElements}
|
||||
</div>
|
||||
<div>
|
||||
{!hasOpenReplyForms
|
||||
? (member ? (isPaidMember || !isPaidOnly ? <MainForm commentsCount={commentCount} /> :
|
||||
<section className={`flex flex-col items-center pt-[40px] ${member ? 'pb-[32px]' : 'pb-[48px]'} ${!isFirst && 'mt-4'} ${(!member || (member && isPaidOnly)) && commentCount ? 'border-t' : 'border-none'} border-[rgba(0,0,0,0.075)] sm:px-8 dark:border-[rgba(255,255,255,0.1)]`} data-testid="cta-box">
|
||||
<CTABox isFirst={isFirst} isPaid={isPaidOnly} />
|
||||
</section>) :
|
||||
<section className={`flex flex-col items-center pt-[40px] ${member ? 'pb-[32px]' : 'pb-[48px]'} ${!isFirst && 'mt-4'} ${(!member || (member && isPaidOnly)) && commentCount ? 'border-t' : 'border-none'} border-[rgba(0,0,0,0.075)] sm:px-8 dark:border-[rgba(255,255,255,0.1)]`} data-testid="cta-box">
|
||||
<CTABox isFirst={isFirst} isPaid={isPaidOnly} />
|
||||
</section>)
|
||||
: null
|
||||
}
|
||||
</div>
|
||||
{
|
||||
labs?.testFlag ? <div data-testid="this-comes-from-a-flag" style={{display: 'none'}}></div> : null // do not remove
|
||||
}
|
||||
</>
|
||||
)
|
||||
)}
|
||||
<div className={`z-10 transition-opacity duration-100 ${commentsIsLoading ? 'opacity-50' : ''}`} data-testid="comment-elements">
|
||||
{commentsComponents}
|
||||
</div>
|
||||
<Pagination />
|
||||
{
|
||||
labs?.testFlag ? <div data-testid="this-comes-from-a-flag" style={{display: 'none'}}></div> : null
|
||||
}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
32
apps/comments-ui/src/components/content/Pagination.test.jsx
Normal file
32
apps/comments-ui/src/components/content/Pagination.test.jsx
Normal file
|
@ -0,0 +1,32 @@
|
|||
import Pagination from './Pagination';
|
||||
import {AppContext} from '../../AppContext';
|
||||
import {render, screen} from '@testing-library/react';
|
||||
|
||||
const contextualRender = (ui, {appContext, ...renderOptions}) => {
|
||||
const contextWithDefaults = {
|
||||
t: (str, replacements) => {
|
||||
if (replacements) {
|
||||
return str.replace(/{{([^{}]*)}}/g, (_, key) => replacements[key]);
|
||||
}
|
||||
return str;
|
||||
},
|
||||
...appContext
|
||||
};
|
||||
|
||||
return render(
|
||||
<AppContext.Provider value={contextWithDefaults}>{ui}</AppContext.Provider>,
|
||||
renderOptions
|
||||
);
|
||||
};
|
||||
|
||||
describe('<Pagination>', function () {
|
||||
it('has correct text for 1 more', function () {
|
||||
contextualRender(<Pagination />, {appContext: {pagination: {total: 4, page: 1, limit: 3}}});
|
||||
expect(screen.getByText('Load more (1)')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('has correct text for x more', function () {
|
||||
contextualRender(<Pagination />, {appContext: {pagination: {total: 6, page: 1, limit: 3}}});
|
||||
expect(screen.getByText('Load more (3)')).toBeInTheDocument();
|
||||
});
|
||||
});
|
|
@ -1,9 +1,8 @@
|
|||
import {formatNumber} from '../../utils/helpers';
|
||||
import {useAppContext, useLabs} from '../../AppContext';
|
||||
import {useAppContext} from '../../AppContext';
|
||||
|
||||
const Pagination = () => {
|
||||
const {pagination, dispatchAction, t} = useAppContext();
|
||||
const labs = useLabs();
|
||||
|
||||
const loadMore = () => {
|
||||
dispatchAction('loadMoreComments', {});
|
||||
|
@ -13,27 +12,18 @@ const Pagination = () => {
|
|||
return null;
|
||||
}
|
||||
|
||||
const left = pagination.total - pagination.page * pagination.limit;
|
||||
const commentsLeft = pagination.total - pagination.page * pagination.limit;
|
||||
|
||||
if (left <= 0) {
|
||||
if (commentsLeft <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: add i18n support for these strings when removing labs flag
|
||||
const text = labs.commentImprovements
|
||||
? (left === 1 ? 'Load more (1)' : `Load more (${formatNumber(left)})`)
|
||||
: (left === 1 ? t('Show 1 previous comment') : t('Show {{amount}} previous comments', {amount: formatNumber(left)}));
|
||||
const text = t(`Load more ({{amount}})`, {amount: formatNumber(commentsLeft)});
|
||||
|
||||
return (
|
||||
labs.commentImprovements ? (
|
||||
<button className="text-md group mb-10 flex items-center px-0 pb-2 pt-0 text-left font-sans font-semibold text-neutral-700 dark:text-white" data-testid="pagination-component" type="button" onClick={loadMore}>
|
||||
<span className="flex h-[40px] items-center justify-center whitespace-nowrap rounded-[6px] bg-black/5 px-4 py-2 text-center font-sans text-sm font-semibold text-neutral-700 outline-0 transition-all duration-150 hover:bg-black/10 dark:bg-white/15 dark:text-neutral-300 dark:hover:bg-white/20 dark:hover:text-neutral-100">{text}</span>
|
||||
</button>
|
||||
) : (
|
||||
<button className="text-md group mb-10 flex w-full items-center px-0 pb-2 pt-0 text-left font-sans font-semibold text-neutral-700 dark:text-white" data-testid="pagination-component" type="button" onClick={loadMore}>
|
||||
<span className="flex h-[40px] w-full items-center justify-center whitespace-nowrap rounded-[6px] bg-black/5 px-3 py-2 text-center font-sans text-sm font-semibold text-neutral-700 outline-0 transition-all duration-150 hover:bg-black/10 dark:bg-white/15 dark:text-neutral-300 dark:hover:bg-white/20 dark:hover:text-neutral-100">↑ {text}</span>
|
||||
</button>
|
||||
)
|
||||
<button className="text-md group mb-10 flex items-center px-0 pb-2 pt-0 text-left font-sans font-semibold text-neutral-700 dark:text-white" data-testid="pagination-component" type="button" onClick={loadMore}>
|
||||
<span className="flex h-[40px] items-center justify-center whitespace-nowrap rounded-[6px] bg-black/5 px-4 py-2 text-center font-sans text-sm font-semibold text-neutral-700 outline-0 transition-all duration-150 hover:bg-black/10 dark:bg-white/15 dark:text-neutral-300 dark:hover:bg-white/20 dark:hover:text-neutral-100">{text}</span>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {Comment, useAppContext, useLabs} from '../../../AppContext';
|
||||
import {Comment, useAppContext} from '../../../AppContext';
|
||||
import {ReactComponent as LikeIcon} from '../../../images/icons/like.svg';
|
||||
import {useState} from 'react';
|
||||
|
||||
|
@ -7,7 +7,6 @@ type Props = {
|
|||
};
|
||||
const LikeButton: React.FC<Props> = ({comment}) => {
|
||||
const {dispatchAction, member, commentsEnabled} = useAppContext();
|
||||
const labs = useLabs();
|
||||
const [animationClass, setAnimation] = useState('');
|
||||
|
||||
const paidOnly = commentsEnabled === 'paid';
|
||||
|
@ -15,13 +14,11 @@ const LikeButton: React.FC<Props> = ({comment}) => {
|
|||
const canLike = member && (isPaidMember || !paidOnly);
|
||||
|
||||
const toggleLike = () => {
|
||||
if (!canLike && labs && labs.commentImprovements) {
|
||||
if (!canLike) {
|
||||
dispatchAction('openPopup', {
|
||||
type: 'ctaPopup'
|
||||
});
|
||||
return;
|
||||
} else if (!canLike) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!comment.liked) {
|
||||
|
@ -35,39 +32,22 @@ const LikeButton: React.FC<Props> = ({comment}) => {
|
|||
}
|
||||
};
|
||||
|
||||
// If can like: use <button> element, otherwise use a <span>
|
||||
const CustomTag = canLike ? `button` : `span`;
|
||||
|
||||
let likeCursor = 'cursor-pointer';
|
||||
if (!canLike) {
|
||||
likeCursor = 'cursor-text';
|
||||
}
|
||||
|
||||
if (labs && labs.commentImprovements) {
|
||||
return (
|
||||
<button
|
||||
className={`duration-50 group flex cursor-pointer items-center font-sans text-base outline-0 transition-all ease-linear sm:text-sm ${
|
||||
comment.liked ? 'text-black/90 dark:text-white/90' : 'text-black/50 hover:text-black/75 dark:text-white/60 dark:hover:text-white/75'
|
||||
}`}
|
||||
data-testid="like-button"
|
||||
type="button"
|
||||
onClick={toggleLike}
|
||||
>
|
||||
<LikeIcon
|
||||
className={animationClass + ` mr-[6px] ${
|
||||
comment.liked ? 'fill-black dark:fill-white stroke-black dark:stroke-white' : 'stroke-black/50 group-hover:stroke-black/75 dark:stroke-white/60 dark:group-hover:stroke-white/75'
|
||||
} ${!comment.liked && canLike && 'group-hover:stroke-black/75 dark:group-hover:stroke-white/75'} transition duration-50 ease-linear`}
|
||||
/>
|
||||
{comment.count.likes}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<CustomTag className={`duration-50 group flex items-center font-sans text-base outline-0 transition-all ease-linear sm:text-sm ${comment.liked ? 'text-black/90 dark:text-white/90' : 'text-black/50 hover:text-black/75 dark:text-white/60 dark:hover:text-white/75'} ${likeCursor}`} data-testid="like-button" type="button" onClick={toggleLike}>
|
||||
<LikeIcon className={animationClass + ` mr-[6px] ${comment.liked ? 'fill-black dark:fill-white stroke-black dark:stroke-white' : 'stroke-black/50 group-hover:stroke-black/75 dark:stroke-white/60 dark:group-hover:stroke-white/75'} ${!comment.liked && canLike && 'group-hover:stroke-black/75 dark:group-hover:stroke-white/75'} transition duration-50 ease-linear`} />
|
||||
<button
|
||||
className={`duration-50 group flex cursor-pointer items-center font-sans text-base outline-0 transition-all ease-linear sm:text-sm ${
|
||||
comment.liked ? 'text-black/90 dark:text-white/90' : 'text-black/50 hover:text-black/75 dark:text-white/60 dark:hover:text-white/75'
|
||||
}`}
|
||||
data-testid="like-button"
|
||||
type="button"
|
||||
onClick={toggleLike}
|
||||
>
|
||||
<LikeIcon
|
||||
className={animationClass + ` mr-[6px] ${
|
||||
comment.liked ? 'fill-black dark:fill-white stroke-black dark:stroke-white' : 'stroke-black/50 group-hover:stroke-black/75 dark:stroke-white/60 dark:group-hover:stroke-white/75'
|
||||
} ${!comment.liked && canLike && 'group-hover:stroke-black/75 dark:group-hover:stroke-white/75'} transition duration-50 ease-linear`}
|
||||
/>
|
||||
{comment.count.likes}
|
||||
</CustomTag>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {ReactComponent as ReplyIcon} from '../../../images/icons/reply.svg';
|
||||
import {useAppContext, useLabs} from '../../../AppContext';
|
||||
import {useAppContext} from '../../../AppContext';
|
||||
|
||||
type Props = {
|
||||
disabled?: boolean;
|
||||
|
@ -9,14 +9,13 @@ type Props = {
|
|||
|
||||
const ReplyButton: React.FC<Props> = ({disabled, isReplying, openReplyForm}) => {
|
||||
const {member, t, dispatchAction, commentsEnabled} = useAppContext();
|
||||
const labs = useLabs();
|
||||
|
||||
const paidOnly = commentsEnabled === 'paid';
|
||||
const isPaidMember = member && !!member.paid;
|
||||
const canReply = member && (isPaidMember || !paidOnly);
|
||||
|
||||
const handleClick = () => {
|
||||
if (!canReply && labs && labs.commentImprovements) {
|
||||
if (!canReply) {
|
||||
dispatchAction('openPopup', {
|
||||
type: 'ctaPopup'
|
||||
});
|
||||
|
@ -25,10 +24,6 @@ const ReplyButton: React.FC<Props> = ({disabled, isReplying, openReplyForm}) =>
|
|||
openReplyForm();
|
||||
};
|
||||
|
||||
if (!member && !labs?.commentImprovements) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
className={`duration-50 group flex items-center font-sans text-base outline-0 transition-all ease-linear sm:text-sm ${isReplying ? 'text-black/90 dark:text-white/90' : 'text-black/50 hover:text-black/75 dark:text-white/60 dark:hover:text-white/75'}`}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import {Comment, useAppContext, useLabs} from '../../../AppContext';
|
||||
import {Comment, useAppContext} from '../../../AppContext';
|
||||
|
||||
type Props = {
|
||||
comment: Comment;
|
||||
|
@ -8,17 +8,12 @@ type Props = {
|
|||
};
|
||||
const AuthorContextMenu: React.FC<Props> = ({comment, close, toggleEdit}) => {
|
||||
const {dispatchAction, t} = useAppContext();
|
||||
const labs = useLabs();
|
||||
|
||||
const deleteComment = () => {
|
||||
if (labs.commentImprovements) {
|
||||
dispatchAction('openPopup', {
|
||||
type: 'deletePopup',
|
||||
comment
|
||||
});
|
||||
} else {
|
||||
dispatchAction('deleteComment', comment);
|
||||
}
|
||||
dispatchAction('openPopup', {
|
||||
type: 'deletePopup',
|
||||
comment
|
||||
});
|
||||
close();
|
||||
};
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ describe('<CommentContextMenu>', () => {
|
|||
|
||||
it('has display-below classes when in viewport', () => {
|
||||
const comment = buildComment();
|
||||
contextualRender(<CommentContextMenu comment={comment} />, {appContext: {admin: true, labs: {commentImprovements: true}}});
|
||||
contextualRender(<CommentContextMenu comment={comment} />, {appContext: {admin: true}});
|
||||
expect(screen.getByTestId('comment-context-menu-inner')).toHaveClass('top-0');
|
||||
});
|
||||
|
||||
|
@ -34,7 +34,7 @@ describe('<CommentContextMenu>', () => {
|
|||
sinon.stub(HTMLElement.prototype, 'getBoundingClientRect').returns({bottom: 2000});
|
||||
|
||||
const comment = buildComment();
|
||||
contextualRender(<CommentContextMenu comment={comment} />, {appContext: {admin: true, labs: {commentImprovements: true}}});
|
||||
contextualRender(<CommentContextMenu comment={comment} />, {appContext: {admin: true}});
|
||||
expect(screen.getByTestId('comment-context-menu-inner')).toHaveClass('bottom-full', 'mb-6');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import AdminContextMenu from './AdminContextMenu';
|
||||
import AuthorContextMenu from './AuthorContextMenu';
|
||||
import NotAuthorContextMenu from './NotAuthorContextMenu';
|
||||
import {Comment, useAppContext, useLabs} from '../../../AppContext';
|
||||
import {Comment, useAppContext} from '../../../AppContext';
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {useOutOfViewportClasses} from '../../../utils/hooks';
|
||||
|
||||
|
@ -16,10 +16,8 @@ const CommentContextMenu: React.FC<Props> = ({comment, close, toggleEdit}) => {
|
|||
const isAdmin = !!admin;
|
||||
const element = useRef<HTMLDivElement>(null);
|
||||
const innerElement = useRef<HTMLDivElement>(null);
|
||||
const labs = useLabs();
|
||||
|
||||
// By default display dropdown below but move above if that renders off-screen
|
||||
// NOTE: innerElement ref is only set when commentImprovements flag is enabled
|
||||
useOutOfViewportClasses(innerElement, {
|
||||
bottom: {
|
||||
default: 'top-0',
|
||||
|
@ -88,19 +86,11 @@ const CommentContextMenu: React.FC<Props> = ({comment, close, toggleEdit}) => {
|
|||
}
|
||||
|
||||
return (
|
||||
labs.commentImprovements ? (
|
||||
<div ref={element} className="relative" data-testid="comment-context-menu" onClick={stopPropagation}>
|
||||
<div ref={innerElement} className={`absolute z-10 min-w-min whitespace-nowrap rounded bg-white p-1 font-sans text-sm shadow-lg outline-0 sm:min-w-[80px] dark:bg-neutral-800 dark:text-white`} data-testid="comment-context-menu-inner">
|
||||
{contextMenu}
|
||||
</div>
|
||||
<div ref={element} className="relative" data-testid="comment-context-menu" onClick={stopPropagation}>
|
||||
<div ref={innerElement} className={`absolute z-10 min-w-min whitespace-nowrap rounded bg-white p-1 font-sans text-sm shadow-lg outline-0 sm:min-w-[80px] dark:bg-neutral-800 dark:text-white`} data-testid="comment-context-menu-inner">
|
||||
{contextMenu}
|
||||
</div>
|
||||
) : (
|
||||
<div ref={element} onClick={stopPropagation}>
|
||||
<div className="absolute z-10 min-w-min whitespace-nowrap rounded bg-white p-1 font-sans text-sm shadow-lg outline-0 sm:min-w-[80px] dark:bg-neutral-800 dark:text-white">
|
||||
{contextMenu}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import {Avatar} from '../Avatar';
|
||||
import {Comment, OpenCommentForm, useAppContext, useLabs} from '../../../AppContext';
|
||||
import {Comment, OpenCommentForm, useAppContext} from '../../../AppContext';
|
||||
import {ReactComponent as EditIcon} from '../../../images/icons/edit.svg';
|
||||
import {Editor, EditorContent} from '@tiptap/react';
|
||||
import {ReactComponent as SpinnerIcon} from '../../../images/icons/spinner.svg';
|
||||
|
@ -25,7 +25,6 @@ export type FormEditorProps = {
|
|||
};
|
||||
|
||||
export const FormEditor: React.FC<FormEditorProps> = ({comment, submit, progress, setProgress, close, isOpen, editor, submitText, submitSize, openForm}) => {
|
||||
const labs = useLabs();
|
||||
const {dispatchAction, t} = useAppContext();
|
||||
let buttonIcon = null;
|
||||
|
||||
|
@ -55,7 +54,7 @@ export const FormEditor: React.FC<FormEditorProps> = ({comment, submit, progress
|
|||
}, [editor, comment, openForm, dispatchAction]);
|
||||
|
||||
if (progress === 'sending') {
|
||||
buttonIcon = <SpinnerIcon className={`h-[24px] w-[24px] fill-white ${labs.commentImprovements ? '' : 'dark:fill-black'}`} data-testid="button-spinner" />;
|
||||
buttonIcon = <SpinnerIcon className={`h-[24px] w-[24px] fill-white`} data-testid="button-spinner" />;
|
||||
}
|
||||
|
||||
const stopIfFocused = useCallback((event) => {
|
||||
|
@ -144,28 +143,16 @@ export const FormEditor: React.FC<FormEditorProps> = ({comment, submit, progress
|
|||
{close &&
|
||||
<button className="ml-2.5 font-sans text-sm font-medium text-neutral-900/50 outline-0 transition-all hover:text-neutral-900/70 dark:text-white/60 dark:hover:text-white/75" type="button" onClick={close}>{t('Cancel')}</button>
|
||||
}
|
||||
{labs.commentImprovements ? (
|
||||
<button
|
||||
className={`flex w-auto items-center justify-center ${submitSize === 'medium' && 'sm:min-w-[100px]'} ${submitSize === 'small' && 'sm:min-w-[64px]'} h-[40px] rounded-md bg-[var(--gh-accent-color)] px-3 py-2 text-center font-sans text-base font-medium text-white outline-0 transition-colors duration-200 hover:brightness-105 disabled:bg-black/5 disabled:text-neutral-900/30 sm:text-sm dark:disabled:bg-white/15 dark:disabled:text-white/35`}
|
||||
data-testid="submit-form-button"
|
||||
disabled={!editor || editor.isEmpty}
|
||||
type="button"
|
||||
onClick={submitForm}
|
||||
>
|
||||
{buttonIcon && <span className="mr-1">{buttonIcon}</span>}
|
||||
{submitText && <span>{submitText}</span>}
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
className={`flex w-auto items-center justify-center ${submitSize === 'medium' && 'sm:min-w-[100px]'} ${submitSize === 'small' && 'sm:min-w-[64px]'} h-[40px] rounded-[6px] bg-neutral-900 px-3 py-2 text-center font-sans text-base font-medium text-white/95 outline-0 transition-all duration-150 hover:bg-black hover:text-white sm:text-sm dark:bg-white/95 dark:text-neutral-800 dark:hover:bg-white dark:hover:text-neutral-900`}
|
||||
data-testid="submit-form-button"
|
||||
type="button"
|
||||
onClick={submitForm}
|
||||
>
|
||||
<span>{buttonIcon}</span>
|
||||
{submitText && <span>{submitText}</span>}
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
className={`flex w-auto items-center justify-center ${submitSize === 'medium' && 'sm:min-w-[100px]'} ${submitSize === 'small' && 'sm:min-w-[64px]'} h-[40px] rounded-md bg-[var(--gh-accent-color)] px-3 py-2 text-center font-sans text-base font-medium text-white outline-0 transition-colors duration-200 hover:brightness-105 disabled:bg-black/5 disabled:text-neutral-900/30 sm:text-sm dark:disabled:bg-white/15 dark:disabled:text-white/35`}
|
||||
data-testid="submit-form-button"
|
||||
disabled={!editor || editor.isEmpty}
|
||||
type="button"
|
||||
onClick={submitForm}
|
||||
>
|
||||
{buttonIcon && <span className="mr-1">{buttonIcon}</span>}
|
||||
{submitText && <span>{submitText}</span>}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -183,9 +170,8 @@ type FormHeaderProps = {
|
|||
|
||||
const FormHeader: React.FC<FormHeaderProps> = ({show, name, expertise, replyingToText, editName, editExpertise}) => {
|
||||
const {t} = useAppContext();
|
||||
const labs = useLabs();
|
||||
|
||||
const isReplyingToReply = labs.commentImprovements && replyingToText;
|
||||
const isReplyingToReply = !!replyingToText;
|
||||
|
||||
return (
|
||||
<Transition
|
||||
|
@ -320,14 +306,13 @@ const FormWrapper: React.FC<FormWrapperProps> = ({
|
|||
children
|
||||
}) => {
|
||||
const {member, dispatchAction} = useAppContext();
|
||||
const labs = useLabs();
|
||||
|
||||
const memberName = member?.name ?? comment?.member?.name;
|
||||
const memberExpertise = member?.expertise ?? comment?.member?.expertise;
|
||||
|
||||
let openStyles = '';
|
||||
if (isOpen) {
|
||||
const isReplyToReply = labs.commentImprovements && !!openForm?.in_reply_to_snippet;
|
||||
const isReplyToReply = !!openForm?.in_reply_to_snippet;
|
||||
openStyles = isReplyToReply ? 'pl-[1px] pt-[68px] sm:pl-[44px] sm:pt-[56px]' : 'pl-[1px] pt-[48px] sm:pl-[44px] sm:pt-[40px]';
|
||||
}
|
||||
|
||||
|
|
|
@ -10,9 +10,8 @@ test.describe('Actions', async () => {
|
|||
mockedApi,
|
||||
page,
|
||||
publication: 'Publisher Weekly',
|
||||
labs: {
|
||||
commentImprovements: labs
|
||||
}
|
||||
// always return `labs` value for any labs.x property access
|
||||
labs: new Proxy({}, {get: () => labs})
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -26,6 +25,7 @@ test.describe('Actions', async () => {
|
|||
});
|
||||
|
||||
test('Can like and unlike a comment', async ({page}) => {
|
||||
// NOTE: comments are ordered by likes
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is comment 1</p>'
|
||||
});
|
||||
|
@ -43,7 +43,7 @@ test.describe('Actions', async () => {
|
|||
const {frame} = await initializeTest(page);
|
||||
|
||||
// Check like button is not filled yet
|
||||
const comment = frame.getByTestId('comment-component').nth(0);
|
||||
const comment = frame.getByTestId('comment-component').nth(1);
|
||||
const likeButton = comment.getByTestId('like-button');
|
||||
await expect(likeButton).toHaveCount(1);
|
||||
|
||||
|
@ -65,7 +65,7 @@ test.describe('Actions', async () => {
|
|||
await expect(likeButton).toHaveText('0');
|
||||
|
||||
// Check state for already liked comment
|
||||
const secondComment = frame.getByTestId('comment-component').nth(1);
|
||||
const secondComment = frame.getByTestId('comment-component').nth(0);
|
||||
const likeButton2 = secondComment.getByTestId('like-button');
|
||||
await expect(likeButton2).toHaveCount(1);
|
||||
const icon2 = likeButton2.locator('svg');
|
||||
|
@ -120,7 +120,7 @@ test.describe('Actions', async () => {
|
|||
|
||||
// Click button
|
||||
await replyButton.click();
|
||||
const editor = frame.getByTestId('form-editor');
|
||||
const editor = comment.getByTestId('form-editor');
|
||||
await expect(editor).toBeVisible();
|
||||
// Wait for focused
|
||||
await waitEditorFocused(editor);
|
||||
|
@ -145,28 +145,8 @@ test.describe('Actions', async () => {
|
|||
await expect(frame.getByText('This is a reply 123')).toHaveCount(1);
|
||||
});
|
||||
|
||||
test('Reply-to-reply action not shown without labs flag', async ({
|
||||
page
|
||||
}) => {
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is comment 1</p>',
|
||||
replies: [
|
||||
mockedApi.buildReply({
|
||||
html: '<p>This is a reply to 1</p>'
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
const parentComment = frame.getByTestId('comment-component').nth(0);
|
||||
const replyComment = parentComment.getByTestId('comment-component').nth(0);
|
||||
|
||||
expect(replyComment.getByTestId('reply-button')).not.toBeVisible();
|
||||
});
|
||||
|
||||
async function testReplyToReply(page) {
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
const parentComment = frame.getByTestId('comment-component').nth(0);
|
||||
const replyComment = parentComment.getByTestId('comment-component').nth(0);
|
||||
|
@ -174,7 +154,7 @@ test.describe('Actions', async () => {
|
|||
const replyReplyButton = replyComment.getByTestId('reply-button');
|
||||
await replyReplyButton.click();
|
||||
|
||||
const editor = frame.getByTestId('form-editor').nth(1);
|
||||
const editor = parentComment.getByTestId('form-editor');
|
||||
await expect(editor).toBeVisible();
|
||||
await waitEditorFocused(editor);
|
||||
|
||||
|
@ -218,6 +198,20 @@ test.describe('Actions', async () => {
|
|||
await testReplyToReply(page);
|
||||
});
|
||||
|
||||
test('Can reply to a reply with a deleted parent comment', async function ({page}) {
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is comment 1</p>',
|
||||
status: 'deleted',
|
||||
replies: [
|
||||
mockedApi.buildReply({
|
||||
html: '<p>This is a reply to 1</p>'
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
await testReplyToReply(page);
|
||||
});
|
||||
|
||||
test('Can highlight reply when clicking on reply to: snippet', async ({page}) => {
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is comment 1</p>',
|
||||
|
@ -235,7 +229,7 @@ test.describe('Actions', async () => {
|
|||
]
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
await frame.getByTestId('comment-in-reply-to').click();
|
||||
|
||||
|
@ -274,7 +268,7 @@ test.describe('Actions', async () => {
|
|||
]
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
await frame.getByTestId('comment-in-reply-to').click();
|
||||
|
||||
|
@ -300,20 +294,6 @@ test.describe('Actions', async () => {
|
|||
await expect(markElement).not.toBeVisible();
|
||||
});
|
||||
|
||||
test('Can reply to a reply with a deleted parent comment', async function ({page}) {
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is comment 1</p>',
|
||||
status: 'deleted',
|
||||
replies: [
|
||||
mockedApi.buildReply({
|
||||
html: '<p>This is a reply to 1</p>'
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
await testReplyToReply(page);
|
||||
});
|
||||
|
||||
test('Can add expertise', async ({page}) => {
|
||||
mockedApi.setMember({name: 'John Doe', expertise: null});
|
||||
|
||||
|
@ -370,7 +350,7 @@ test.describe('Actions', async () => {
|
|||
member: loggedInMember
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
const comment = frame.getByTestId('comment-component').nth(0);
|
||||
const moreButton = comment.getByTestId('more-button').first();
|
||||
|
@ -399,7 +379,7 @@ test.describe('Actions', async () => {
|
|||
]
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
const comment = frame.getByTestId('comment-component').nth(0);
|
||||
const reply = comment.getByTestId('comment-component').nth(0);
|
||||
|
@ -430,7 +410,7 @@ test.describe('Actions', async () => {
|
|||
]
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
const comment = frame.getByTestId('comment-component').nth(0);
|
||||
const moreButton = comment.getByTestId('more-button').first();
|
||||
|
@ -471,7 +451,7 @@ test.describe('Actions', async () => {
|
|||
html: '<p>This is comment 6</p>'
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
const sortingForm = frame.getByTestId('comments-sorting-form');
|
||||
|
||||
|
@ -501,7 +481,7 @@ test.describe('Actions', async () => {
|
|||
created_at: new Date('2022-02-01T00:00:00Z')
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
const sortingForm = frame.getByTestId('comments-sorting-form');
|
||||
|
||||
|
@ -538,7 +518,7 @@ test.describe('Actions', async () => {
|
|||
html: '<p>This is comment 6</p>'
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
const sortingForm = frame.getByTestId('comments-sorting-form');
|
||||
|
||||
|
@ -575,7 +555,7 @@ test.describe('Actions', async () => {
|
|||
created_at: new Date('2024-04-03T00:00:00Z')
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
const sortingForm = await frame.getByTestId('comments-sorting-form');
|
||||
|
||||
|
@ -618,7 +598,7 @@ test.describe('Actions', async () => {
|
|||
created_at: new Date('2024-04-03T00:00:00Z')
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
const sortingForm = await frame.getByTestId('comments-sorting-form');
|
||||
|
||||
|
@ -657,7 +637,7 @@ test.describe('Actions', async () => {
|
|||
created_at: new Date('2024-04-03T00:00:00Z')
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
const sortingForm = await frame.getByTestId('comments-sorting-form');
|
||||
|
||||
|
@ -720,7 +700,7 @@ test.describe('Actions', async () => {
|
|||
await frame.getByTestId('edit').click();
|
||||
|
||||
// Verify the edit form is visible
|
||||
await expect(frame.getByTestId('form-editor')).toBeVisible();
|
||||
await expect(parentComment.getByTestId('form-editor')).toBeVisible();
|
||||
|
||||
// Verify replies are still visible while editing
|
||||
await expect(replies[0]).toBeVisible();
|
||||
|
|
|
@ -28,7 +28,7 @@ test.describe('Admin moderation', async () => {
|
|||
mockedApi.setMember(options.member);
|
||||
|
||||
if (options.labs) {
|
||||
mockedApi.setLabs({commentImprovements: true});
|
||||
// enable specific labs flags here
|
||||
}
|
||||
|
||||
return await initialize({
|
||||
|
@ -39,7 +39,7 @@ test.describe('Admin moderation', async () => {
|
|||
count: true,
|
||||
admin,
|
||||
labs: {
|
||||
commentImprovements: options.labs
|
||||
// enable specific labs flags here
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -101,241 +101,216 @@ test.describe('Admin moderation', async () => {
|
|||
await expect(frame.getByTestId('hide-button')).toBeVisible();
|
||||
});
|
||||
|
||||
test('can hide and show comments', async ({page}) => {
|
||||
test('member uuid are passed to admin browse api params', async ({page}) => {
|
||||
mockedApi.addComment({html: '<p>This is comment 1</p>'});
|
||||
mockedApi.addComment({html: '<p>This is comment 2</p>'});
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'browseComments');
|
||||
const {frame} = await initializeTest(page);
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
await expect(comments).toHaveCount(1);
|
||||
expect(adminBrowseSpy.called).toBe(true);
|
||||
const lastCall = adminBrowseSpy.lastCall.args[0];
|
||||
const url = new URL(lastCall.request().url());
|
||||
expect(url.searchParams.get('impersonate_member_uuid')).toBe('12345');
|
||||
});
|
||||
|
||||
test('member uuid gets set when loading more comments', async ({page}) => {
|
||||
// create 25 comments
|
||||
for (let i = 0; i < 25; i++) {
|
||||
mockedApi.addComment({html: `<p>This is comment ${i}</p>`});
|
||||
}
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'browseComments');
|
||||
const {frame} = await initializeTest(page);
|
||||
await frame.getByTestId('pagination-component').click();
|
||||
const lastCall = adminBrowseSpy.lastCall.args[0];
|
||||
const url = new URL(lastCall.request().url());
|
||||
expect(url.searchParams.get('impersonate_member_uuid')).toBe('12345');
|
||||
});
|
||||
|
||||
test('member uuid gets set when changing order', async ({page}) => {
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is the oldest</p>',
|
||||
created_at: new Date('2024-02-01T00:00:00Z')
|
||||
});
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is comment 2</p>',
|
||||
created_at: new Date('2024-03-02T00:00:00Z')
|
||||
});
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is the newest comment</p>',
|
||||
created_at: new Date('2024-04-03T00:00:00Z')
|
||||
});
|
||||
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'browseComments');
|
||||
const {frame} = await initializeTest(page);
|
||||
|
||||
// Click the hide button for 2nd comment
|
||||
const sortingForm = await frame.getByTestId('comments-sorting-form');
|
||||
|
||||
await sortingForm.click();
|
||||
|
||||
const sortingDropdown = await frame.getByTestId(
|
||||
'comments-sorting-form-dropdown'
|
||||
);
|
||||
|
||||
const optionSelect = await sortingDropdown.getByText('Newest');
|
||||
mockedApi.setDelay(100);
|
||||
await optionSelect.click();
|
||||
const lastCall = adminBrowseSpy.lastCall.args[0];
|
||||
const url = new URL(lastCall.request().url());
|
||||
expect(url.searchParams.get('impersonate_member_uuid')).toBe('12345');
|
||||
});
|
||||
|
||||
test('member uuid gets set when loading more replies', async ({page}) => {
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is comment 1</p>',
|
||||
replies: [
|
||||
buildReply({html: '<p>This is reply 1</p>'}),
|
||||
buildReply({html: '<p>This is reply 2</p>'}),
|
||||
buildReply({html: '<p>This is reply 3</p>'}),
|
||||
buildReply({html: '<p>This is reply 4</p>'}),
|
||||
buildReply({html: '<p>This is reply 5</p>'}),
|
||||
buildReply({html: '<p>This is reply 6</p>'})
|
||||
]
|
||||
});
|
||||
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'getReplies');
|
||||
const {frame} = await initializeTest(page);
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
const comment = comments.nth(0);
|
||||
await comment.getByTestId('reply-pagination-button').click();
|
||||
const lastCall = adminBrowseSpy.lastCall.args[0];
|
||||
const url = new URL(lastCall.request().url());
|
||||
expect(url.searchParams.get('impersonate_member_uuid')).toBe('12345');
|
||||
});
|
||||
|
||||
test('member uuid gets set when reading a comment (after unhiding)', async ({page}) => {
|
||||
mockedApi.addComment({html: '<p>This is comment 1</p>'});
|
||||
mockedApi.addComment({html: '<p>This is comment 2</p>', status: 'hidden'});
|
||||
const adminReadSpy = sinon.spy(mockedApi.adminRequestHandlers, 'getOrUpdateComment');
|
||||
const {frame} = await initializeTest(page);
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
await expect(comments).toHaveCount(2);
|
||||
await expect(comments.nth(1)).toContainText('Hidden for members');
|
||||
const moreButtons = comments.nth(1).getByTestId('more-button');
|
||||
await moreButtons.click();
|
||||
await moreButtons.getByTestId('show-button').click();
|
||||
await expect(comments.nth(1)).not.toContainText('Hidden for members');
|
||||
|
||||
const lastCall = adminReadSpy.lastCall.args[0];
|
||||
const url = new URL(lastCall.request().url());
|
||||
|
||||
expect(url.searchParams.get('impersonate_member_uuid')).toBe('12345');
|
||||
});
|
||||
|
||||
test('hidden comments are not displayed for non-admins', async ({page}) => {
|
||||
mockedApi.addComment({html: '<p>This is comment 1</p>'});
|
||||
mockedApi.addComment({html: '<p>This is comment 2</p>', status: 'hidden'});
|
||||
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'browseComments');
|
||||
|
||||
const {frame} = await initializeTest(page, {isAdmin: false});
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
await expect(comments).toHaveCount(1);
|
||||
|
||||
expect(adminBrowseSpy.called).toBe(false);
|
||||
});
|
||||
|
||||
test('hidden comments are displayed for admins', async ({page}) => {
|
||||
mockedApi.addComment({html: '<p>This is comment 1</p>'});
|
||||
mockedApi.addComment({html: '<p>This is comment 2</p>', status: 'hidden'});
|
||||
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'browseComments');
|
||||
|
||||
const {frame} = await initializeTest(page);
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
await expect(comments).toHaveCount(2);
|
||||
await expect(comments.nth(1)).toContainText('Hidden for members');
|
||||
|
||||
expect(adminBrowseSpy.called).toBe(true);
|
||||
});
|
||||
|
||||
test('can hide and show comments', async ({page}) => {
|
||||
[1,2].forEach(i => mockedApi.addComment({html: `<p>This is comment ${i}</p>`}));
|
||||
|
||||
const {frame} = await initializeTest(page);
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
|
||||
// Hide the 2nd comment
|
||||
const moreButtons = frame.getByTestId('more-button');
|
||||
await moreButtons.nth(1).click();
|
||||
await moreButtons.nth(1).getByTestId('hide-button').click();
|
||||
await moreButtons.nth(1).getByText('Hide comment').click();
|
||||
|
||||
// comment becomes hidden
|
||||
const comments = frame.getByTestId('comment-component');
|
||||
const secondComment = comments.nth(1);
|
||||
await expect(secondComment).toContainText('This comment has been hidden.');
|
||||
await expect(secondComment).not.toContainText('This is comment 2');
|
||||
await expect(secondComment).toContainText('Hidden for members');
|
||||
|
||||
// can show it again
|
||||
// Check can show it again
|
||||
await moreButtons.nth(1).click();
|
||||
await moreButtons.nth(1).getByTestId('show-button').click();
|
||||
await moreButtons.nth(1).getByText('Show comment').click();
|
||||
await expect(secondComment).toContainText('This is comment 2');
|
||||
});
|
||||
|
||||
test.describe('commentImprovements', function () {
|
||||
test('memeber uuid are passed to admin browse api params', async ({page}) => {
|
||||
mockedApi.addComment({html: '<p>This is comment 1</p>'});
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'browseComments');
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
await expect(comments).toHaveCount(1);
|
||||
expect(adminBrowseSpy.called).toBe(true);
|
||||
const lastCall = adminBrowseSpy.lastCall.args[0];
|
||||
const url = new URL(lastCall.request().url());
|
||||
expect(url.searchParams.get('impersonate_member_uuid')).toBe('12345');
|
||||
test('can hide and show replies', async ({page}) => {
|
||||
mockedApi.addComment({
|
||||
id: '1',
|
||||
html: '<p>This is comment 1</p>',
|
||||
replies: [
|
||||
buildReply({id: '2', html: '<p>This is reply 1</p>'}),
|
||||
buildReply({id: '3', html: '<p>This is reply 2</p>'})
|
||||
]
|
||||
});
|
||||
|
||||
test('member uuid gets set when loading more comments', async ({page}) => {
|
||||
// create 25 comments
|
||||
for (let i = 0; i < 25; i++) {
|
||||
mockedApi.addComment({html: `<p>This is comment ${i}</p>`});
|
||||
}
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'browseComments');
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
await frame.getByTestId('pagination-component').click();
|
||||
const lastCall = adminBrowseSpy.lastCall.args[0];
|
||||
const url = new URL(lastCall.request().url());
|
||||
expect(url.searchParams.get('impersonate_member_uuid')).toBe('12345');
|
||||
const {frame} = await initializeTest(page);
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
const replyToHide = comments.nth(1);
|
||||
|
||||
// Hide the 1st reply
|
||||
await replyToHide.getByTestId('more-button').click();
|
||||
await replyToHide.getByTestId('hide-button').click();
|
||||
|
||||
await expect(replyToHide).toContainText('Hidden for members');
|
||||
|
||||
// Show it again
|
||||
await replyToHide.getByTestId('more-button').click();
|
||||
await replyToHide.getByTestId('show-button').click();
|
||||
|
||||
await expect(replyToHide).not.toContainText('Hidden for members');
|
||||
});
|
||||
|
||||
test('updates in-reply-to snippets when hiding', async ({page}) => {
|
||||
mockedApi.addComment({
|
||||
id: '1',
|
||||
html: '<p>This is comment 1</p>',
|
||||
replies: [
|
||||
buildReply({id: '2', html: '<p>This is reply 1</p>'}),
|
||||
buildReply({id: '3', html: '<p>This is reply 2</p>', in_reply_to_id: '2', in_reply_to_snippet: 'This is reply 1'}),
|
||||
buildReply({id: '4', html: '<p>This is reply 3</p>'})
|
||||
]
|
||||
});
|
||||
|
||||
test('member uuid gets set when changing order', async ({page}) => {
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is the oldest</p>',
|
||||
created_at: new Date('2024-02-01T00:00:00Z')
|
||||
});
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is comment 2</p>',
|
||||
created_at: new Date('2024-03-02T00:00:00Z')
|
||||
});
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is the newest comment</p>',
|
||||
created_at: new Date('2024-04-03T00:00:00Z')
|
||||
});
|
||||
const {frame} = await initializeTest(page);
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
const replyToHide = comments.nth(1);
|
||||
const inReplyToComment = comments.nth(2);
|
||||
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'browseComments');
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
// Hide the 1st reply
|
||||
await replyToHide.getByTestId('more-button').click();
|
||||
await replyToHide.getByTestId('hide-button').click();
|
||||
|
||||
const sortingForm = await frame.getByTestId('comments-sorting-form');
|
||||
await expect(inReplyToComment).toContainText('[removed]');
|
||||
await expect(inReplyToComment).not.toContainText('This is reply 1');
|
||||
|
||||
await sortingForm.click();
|
||||
// Show it again
|
||||
await replyToHide.getByTestId('more-button').click();
|
||||
await replyToHide.getByTestId('show-button').click();
|
||||
|
||||
const sortingDropdown = await frame.getByTestId(
|
||||
'comments-sorting-form-dropdown'
|
||||
);
|
||||
await expect(inReplyToComment).not.toContainText('[removed]');
|
||||
await expect(inReplyToComment).toContainText('This is reply 1');
|
||||
});
|
||||
|
||||
const optionSelect = await sortingDropdown.getByText('Newest');
|
||||
mockedApi.setDelay(100);
|
||||
await optionSelect.click();
|
||||
const lastCall = adminBrowseSpy.lastCall.args[0];
|
||||
const url = new URL(lastCall.request().url());
|
||||
expect(url.searchParams.get('impersonate_member_uuid')).toBe('12345');
|
||||
});
|
||||
test('has correct comments count', async ({page}) => {
|
||||
mockedApi.addComment({html: '<p>This is comment 1</p>', replies: [buildReply()]});
|
||||
mockedApi.addComment({html: '<p>This is comment 2</p>'});
|
||||
|
||||
test('member uuid gets set when loading more replies', async ({page}) => {
|
||||
mockedApi.addComment({
|
||||
html: '<p>This is comment 1</p>',
|
||||
replies: [
|
||||
buildReply({html: '<p>This is reply 1</p>'}),
|
||||
buildReply({html: '<p>This is reply 2</p>'}),
|
||||
buildReply({html: '<p>This is reply 3</p>'}),
|
||||
buildReply({html: '<p>This is reply 4</p>'}),
|
||||
buildReply({html: '<p>This is reply 5</p>'}),
|
||||
buildReply({html: '<p>This is reply 6</p>'})
|
||||
]
|
||||
});
|
||||
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'getReplies');
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
const comment = comments.nth(0);
|
||||
await comment.getByTestId('reply-pagination-button').click();
|
||||
const lastCall = adminBrowseSpy.lastCall.args[0];
|
||||
const url = new URL(lastCall.request().url());
|
||||
expect(url.searchParams.get('impersonate_member_uuid')).toBe('12345');
|
||||
});
|
||||
|
||||
test('member uuid gets set when reading a comment (after unhiding)', async ({page}) => {
|
||||
mockedApi.addComment({html: '<p>This is comment 1</p>'});
|
||||
mockedApi.addComment({html: '<p>This is comment 2</p>', status: 'hidden'});
|
||||
const adminReadSpy = sinon.spy(mockedApi.adminRequestHandlers, 'getOrUpdateComment');
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
await expect(comments).toHaveCount(2);
|
||||
await expect(comments.nth(1)).toContainText('Hidden for members');
|
||||
const moreButtons = comments.nth(1).getByTestId('more-button');
|
||||
await moreButtons.click();
|
||||
await moreButtons.getByTestId('show-button').click();
|
||||
await expect(comments.nth(1)).not.toContainText('Hidden for members');
|
||||
|
||||
const lastCall = adminReadSpy.lastCall.args[0];
|
||||
const url = new URL(lastCall.request().url());
|
||||
|
||||
expect(url.searchParams.get('impersonate_member_uuid')).toBe('12345');
|
||||
});
|
||||
|
||||
test('hidden comments are not displayed for non-admins', async ({page}) => {
|
||||
mockedApi.addComment({html: '<p>This is comment 1</p>'});
|
||||
mockedApi.addComment({html: '<p>This is comment 2</p>', status: 'hidden'});
|
||||
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'browseComments');
|
||||
|
||||
const {frame} = await initializeTest(page, {isAdmin: false, labs: true});
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
await expect(comments).toHaveCount(1);
|
||||
|
||||
expect(adminBrowseSpy.called).toBe(false);
|
||||
});
|
||||
|
||||
test('hidden comments are displayed for admins', async ({page}) => {
|
||||
mockedApi.addComment({html: '<p>This is comment 1</p>'});
|
||||
mockedApi.addComment({html: '<p>This is comment 2</p>', status: 'hidden'});
|
||||
|
||||
const adminBrowseSpy = sinon.spy(mockedApi.adminRequestHandlers, 'browseComments');
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
await expect(comments).toHaveCount(2);
|
||||
await expect(comments.nth(1)).toContainText('Hidden for members');
|
||||
|
||||
expect(adminBrowseSpy.called).toBe(true);
|
||||
});
|
||||
|
||||
test('can hide and show comments', async ({page}) => {
|
||||
[1,2].forEach(i => mockedApi.addComment({html: `<p>This is comment ${i}</p>`}));
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
|
||||
// Hide the 2nd comment
|
||||
const moreButtons = frame.getByTestId('more-button');
|
||||
await moreButtons.nth(1).click();
|
||||
await moreButtons.nth(1).getByText('Hide comment').click();
|
||||
|
||||
const secondComment = comments.nth(1);
|
||||
await expect(secondComment).toContainText('Hidden for members');
|
||||
|
||||
// Check can show it again
|
||||
await moreButtons.nth(1).click();
|
||||
await moreButtons.nth(1).getByText('Show comment').click();
|
||||
await expect(secondComment).toContainText('This is comment 2');
|
||||
});
|
||||
|
||||
test('can hide and show replies', async ({page}) => {
|
||||
mockedApi.addComment({
|
||||
id: '1',
|
||||
html: '<p>This is comment 1</p>',
|
||||
replies: [
|
||||
buildReply({id: '2', html: '<p>This is reply 1</p>'}),
|
||||
buildReply({id: '3', html: '<p>This is reply 2</p>'})
|
||||
]
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
const replyToHide = comments.nth(1);
|
||||
|
||||
// Hide the 1st reply
|
||||
await replyToHide.getByTestId('more-button').click();
|
||||
await replyToHide.getByTestId('hide-button').click();
|
||||
|
||||
await expect(replyToHide).toContainText('Hidden for members');
|
||||
|
||||
// Show it again
|
||||
await replyToHide.getByTestId('more-button').click();
|
||||
await replyToHide.getByTestId('show-button').click();
|
||||
|
||||
await expect(replyToHide).not.toContainText('Hidden for members');
|
||||
});
|
||||
|
||||
test('updates in-reply-to snippets when hiding', async ({page}) => {
|
||||
mockedApi.addComment({
|
||||
id: '1',
|
||||
html: '<p>This is comment 1</p>',
|
||||
replies: [
|
||||
buildReply({id: '2', html: '<p>This is reply 1</p>'}),
|
||||
buildReply({id: '3', html: '<p>This is reply 2</p>', in_reply_to_id: '2', in_reply_to_snippet: 'This is reply 1'}),
|
||||
buildReply({id: '4', html: '<p>This is reply 3</p>'})
|
||||
]
|
||||
});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
const comments = await frame.getByTestId('comment-component');
|
||||
const replyToHide = comments.nth(1);
|
||||
const inReplyToComment = comments.nth(2);
|
||||
|
||||
// Hide the 1st reply
|
||||
await replyToHide.getByTestId('more-button').click();
|
||||
await replyToHide.getByTestId('hide-button').click();
|
||||
|
||||
await expect(inReplyToComment).toContainText('[removed]');
|
||||
await expect(inReplyToComment).not.toContainText('This is reply 1');
|
||||
|
||||
// Show it again
|
||||
await replyToHide.getByTestId('more-button').click();
|
||||
await replyToHide.getByTestId('show-button').click();
|
||||
|
||||
await expect(inReplyToComment).not.toContainText('[removed]');
|
||||
await expect(inReplyToComment).toContainText('This is reply 1');
|
||||
});
|
||||
|
||||
test('has correct comments count', async ({page}) => {
|
||||
mockedApi.addComment({html: '<p>This is comment 1</p>', replies: [buildReply()]});
|
||||
mockedApi.addComment({html: '<p>This is comment 2</p>'});
|
||||
|
||||
const {frame} = await initializeTest(page, {labs: true});
|
||||
await expect(frame.getByTestId('count')).toContainText('3 comments');
|
||||
});
|
||||
const {frame} = await initializeTest(page);
|
||||
await expect(frame.getByTestId('count')).toContainText('3 comments');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -26,9 +26,7 @@ test.describe('Autoclose forms', async () => {
|
|||
mockedApi,
|
||||
page,
|
||||
publication: 'Publisher weekly',
|
||||
labs: {
|
||||
commentImprovements: true
|
||||
}
|
||||
labs: {}
|
||||
}));
|
||||
});
|
||||
|
||||
|
|
|
@ -28,9 +28,7 @@ test.describe('Deleted and Hidden Content', async () => {
|
|||
mockedApi,
|
||||
page,
|
||||
publication: 'Publisher Weekly',
|
||||
labs: {
|
||||
commentImprovements: true
|
||||
}
|
||||
labs: {}
|
||||
});
|
||||
|
||||
const iframeElement = await page.locator('iframe[data-frame="admin-auth"]');
|
||||
|
@ -95,9 +93,7 @@ test.describe('Deleted and Hidden Content', async () => {
|
|||
mockedApi,
|
||||
page,
|
||||
publication: 'Publisher Weekly',
|
||||
labs: {
|
||||
commentImprovements: true
|
||||
}
|
||||
labs: {}
|
||||
});
|
||||
|
||||
await expect (frame.getByText('This is comment 2')).not.toBeVisible();
|
||||
|
@ -131,9 +127,7 @@ test.describe('Deleted and Hidden Content', async () => {
|
|||
mockedApi,
|
||||
page,
|
||||
publication: 'Publisher Weekly',
|
||||
labs: {
|
||||
commentImprovements: true
|
||||
}
|
||||
labs: {}
|
||||
});
|
||||
|
||||
await expect (frame.getByText('This is reply 1')).toBeVisible();
|
||||
|
|
|
@ -19,9 +19,9 @@ test.describe('CTA', async () => {
|
|||
await expect(ctaBox).toContainText('Become a member of Publisher Weekly to start commenting');
|
||||
await expect(ctaBox).toContainText('Sign in');
|
||||
|
||||
// Does not show the reply buttons if not logged in
|
||||
// Show the reply buttons if not logged in
|
||||
const replyButton = frame.getByTestId('reply-button');
|
||||
await expect(replyButton).toHaveCount(0);
|
||||
await expect(replyButton).toHaveCount(2);
|
||||
|
||||
// Does not show the main form
|
||||
const form = frame.getByTestId('form');
|
||||
|
@ -66,9 +66,9 @@ test.describe('CTA', async () => {
|
|||
// Don't show sign in button
|
||||
await expect(ctaBox).not.toContainText('Sign in');
|
||||
|
||||
// No replies or comments possible
|
||||
// Shows replies buttons
|
||||
const replyButton = frame.getByTestId('reply-button');
|
||||
await expect(replyButton).toHaveCount(0);
|
||||
await expect(replyButton).toHaveCount(2);
|
||||
|
||||
const form = frame.getByTestId('form');
|
||||
await expect(form).toHaveCount(0);
|
||||
|
|
|
@ -16,21 +16,22 @@ test.describe('Pagination', async () => {
|
|||
await expect(frame.getByTestId('pagination-component')).toBeVisible();
|
||||
|
||||
// Check text in pagination button
|
||||
await expect(frame.getByTestId('pagination-component')).toContainText('Show 1 previous comment');
|
||||
await expect(frame.getByTestId('pagination-component')).toContainText('Load more (1)');
|
||||
|
||||
// Test total comments with test-id comment-component is 5
|
||||
await expect(frame.getByTestId('comment-component')).toHaveCount(20);
|
||||
|
||||
// Check only the first latest 20 comments are visible
|
||||
await expect(frame.getByText('This is comment 1.')).not.toBeVisible();
|
||||
await expect(frame.getByText('This is comment 1.')).toBeVisible();
|
||||
await expect(frame.getByText('This is comment 2.')).toBeVisible();
|
||||
await expect(frame.getByText('This is comment 3.')).toBeVisible();
|
||||
await expect(frame.getByText('This is comment 4.')).toBeVisible();
|
||||
await expect(frame.getByText('This is comment 5.')).toBeVisible();
|
||||
await expect(frame.getByText('This is comment 6.')).toBeVisible();
|
||||
await expect(frame.getByText('This is comment 20.')).toBeVisible();
|
||||
await expect(frame.getByText('This is comment 21.')).not.toBeVisible();
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
// Click the pagination button
|
||||
await frame.getByTestId('pagination-component').click();
|
||||
|
@ -39,7 +40,7 @@ test.describe('Pagination', async () => {
|
|||
await expect(frame.getByTestId('comment-component')).toHaveCount(21);
|
||||
|
||||
// Check comments 6 is visible
|
||||
await expect(frame.getByText('This is comment 1.')).toBeVisible();
|
||||
await expect(frame.getByText('This is comment 21.')).toBeVisible();
|
||||
|
||||
// Check the pagination button is not visible
|
||||
await expect(frame.getByTestId('pagination-component')).not.toBeVisible();
|
||||
|
|
|
@ -162,10 +162,10 @@ export class MockedApi {
|
|||
|
||||
let filteredComments = this.comments;
|
||||
|
||||
if (this.labs.commentImprovements && !admin) {
|
||||
if (!admin) {
|
||||
function filterPublishedComments(comments: any[] = []) {
|
||||
return comments
|
||||
.filter(comment => comment.status === 'published')
|
||||
.filter(comment => (comment.status === 'published' || comment.replies?.some(r => r.status === 'published')))
|
||||
.map(comment => ({...comment, replies: filterPublishedComments(comment.replies)}));
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ const _ = require('lodash');
|
|||
const utils = require('../../..');
|
||||
const url = require('../utils/url');
|
||||
const htmlToPlaintext = require('@tryghost/html-to-plaintext');
|
||||
const labs = require('../../../../../../../shared/labs');
|
||||
|
||||
const commentFields = [
|
||||
'id',
|
||||
|
@ -48,20 +47,16 @@ const commentMapper = (model, frame) => {
|
|||
|
||||
const isPublicRequest = utils.isMembersAPI(frame);
|
||||
|
||||
if (labs.isSet('commentImprovements')) {
|
||||
if (jsonModel.inReplyTo && (jsonModel.inReplyTo.status === 'published' || (!isPublicRequest && jsonModel.inReplyTo.status === 'hidden'))) {
|
||||
jsonModel.in_reply_to_snippet = htmlToPlaintext.commentSnippet(jsonModel.inReplyTo.html);
|
||||
} else if (jsonModel.inReplyTo && jsonModel.inReplyTo.status !== 'published') {
|
||||
jsonModel.in_reply_to_snippet = '[removed]';
|
||||
} else {
|
||||
jsonModel.in_reply_to_snippet = null;
|
||||
}
|
||||
|
||||
if (!jsonModel.inReplyTo) {
|
||||
jsonModel.in_reply_to_id = null;
|
||||
}
|
||||
if (jsonModel.inReplyTo && (jsonModel.inReplyTo.status === 'published' || (!isPublicRequest && jsonModel.inReplyTo.status === 'hidden'))) {
|
||||
jsonModel.in_reply_to_snippet = htmlToPlaintext.commentSnippet(jsonModel.inReplyTo.html);
|
||||
} else if (jsonModel.inReplyTo && jsonModel.inReplyTo.status !== 'published') {
|
||||
jsonModel.in_reply_to_snippet = '[removed]';
|
||||
} else {
|
||||
delete jsonModel.in_reply_to_id;
|
||||
jsonModel.in_reply_to_snippet = null;
|
||||
}
|
||||
|
||||
if (!jsonModel.inReplyTo) {
|
||||
jsonModel.in_reply_to_id = null;
|
||||
}
|
||||
|
||||
const response = _.pick(jsonModel, commentFields);
|
||||
|
|
|
@ -3,7 +3,6 @@ const _ = require('lodash');
|
|||
const errors = require('@tryghost/errors');
|
||||
const tpl = require('@tryghost/tpl');
|
||||
const {ValidationError} = require('@tryghost/errors');
|
||||
const labs = require('../../shared/labs');
|
||||
|
||||
const messages = {
|
||||
emptyComment: 'The body of a comment cannot be empty',
|
||||
|
@ -62,43 +61,21 @@ const Comment = ghostBookshelf.Model.extend({
|
|||
.query('limit', 3);
|
||||
},
|
||||
|
||||
customQuery(qb) {
|
||||
qb.where(function () {
|
||||
this.whereNotIn('comments.status', ['hidden', 'deleted'])
|
||||
.orWhereExists(function () {
|
||||
this.select(1)
|
||||
.from('comments as replies')
|
||||
.whereRaw('replies.parent_id = comments.id')
|
||||
.whereNotIn('replies.status', ['hidden', 'deleted']);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
adminCustomQuery(qb) {
|
||||
qb.where(function () {
|
||||
this.whereNotIn('comments.status', ['deleted'])
|
||||
.orWhereExists(function () {
|
||||
this.select(1)
|
||||
.from('comments as replies')
|
||||
.whereRaw('replies.parent_id = comments.id')
|
||||
.whereNotIn('replies.status', ['deleted']);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// Called by our filtered-collection bookshelf plugin
|
||||
applyCustomQuery(options) {
|
||||
if (labs.isSet('commentImprovements')) {
|
||||
if (!options.isAdmin) { // if it's an admin request, we don't need to apply the custom query
|
||||
this.query((qb) => {
|
||||
this.customQuery(qb, options);
|
||||
});
|
||||
}
|
||||
if (options.isAdmin) {
|
||||
this.query((qb) => {
|
||||
this.adminCustomQuery(qb, options);
|
||||
});
|
||||
}
|
||||
}
|
||||
const excludedCommentStatuses = options.isAdmin ? ['deleted'] : ['hidden', 'deleted'];
|
||||
|
||||
this.query((qb) => {
|
||||
qb.where(function () {
|
||||
this.whereNotIn('comments.status', excludedCommentStatuses)
|
||||
.orWhereExists(function () {
|
||||
this.select(1)
|
||||
.from('comments as replies')
|
||||
.whereRaw('replies.parent_id = comments.id')
|
||||
.whereNotIn('replies.status', excludedCommentStatuses);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
emitChange: function emitChange(event, options) {
|
||||
|
@ -228,7 +205,7 @@ const Comment = ghostBookshelf.Model.extend({
|
|||
// - public requests never return hidden or deleted replies
|
||||
// - admin requests never return deleted replies but do return hidden replies
|
||||
const repliesOptionIndex = withRelated.indexOf('replies');
|
||||
if (labs.isSet('commentImprovements') && repliesOptionIndex > -1) {
|
||||
if (repliesOptionIndex > -1) {
|
||||
withRelated[repliesOptionIndex] = {
|
||||
replies: (qb) => {
|
||||
if (isAdmin) {
|
||||
|
@ -297,31 +274,15 @@ const Comment = ghostBookshelf.Model.extend({
|
|||
countRelations() {
|
||||
return {
|
||||
replies(modelOrCollection, options) {
|
||||
if (labs.isSet('commentImprovements') && !options.isAdmin) {
|
||||
modelOrCollection.query('columns', 'comments.*', (qb) => {
|
||||
qb.count('replies.id')
|
||||
.from('comments AS replies')
|
||||
.whereRaw('replies.parent_id = comments.id')
|
||||
.whereNotIn('replies.status', ['hidden', 'deleted'])
|
||||
.as('count__replies');
|
||||
});
|
||||
} else {
|
||||
modelOrCollection.query('columns', 'comments.*', (qb) => {
|
||||
qb.count('replies.id')
|
||||
.from('comments AS replies')
|
||||
.whereRaw('replies.parent_id = comments.id')
|
||||
.as('count__replies');
|
||||
});
|
||||
}
|
||||
if (options.isAdmin && labs.isSet('commentImprovements')) {
|
||||
modelOrCollection.query('columns', 'comments.*', (qb) => {
|
||||
qb.count('replies.id')
|
||||
.from('comments AS replies')
|
||||
.whereRaw('replies.parent_id = comments.id')
|
||||
.whereNotIn('replies.status', ['deleted'])
|
||||
.as('count__replies');
|
||||
});
|
||||
}
|
||||
const excludedCommentStatuses = options.isAdmin ? ['deleted'] : ['hidden', 'deleted'];
|
||||
|
||||
modelOrCollection.query('columns', 'comments.*', (qb) => {
|
||||
qb.count('replies.id')
|
||||
.from('comments AS replies')
|
||||
.whereRaw('replies.parent_id = comments.id')
|
||||
.whereNotIn('replies.status', excludedCommentStatuses)
|
||||
.as('count__replies');
|
||||
});
|
||||
},
|
||||
likes(modelOrCollection) {
|
||||
modelOrCollection.query('columns', 'comments.*', (qb) => {
|
||||
|
|
|
@ -1,172 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Admin Comments API - commentImprovements off Hide Can hide comments 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
"count": Object {
|
||||
"likes": Any<Number>,
|
||||
"replies": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"expertise": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Mr Egg",
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"replies": Array [],
|
||||
"status": "published",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements off Hide Can hide comments 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "361",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements off Hide Can hide comments 3: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
"count": Object {
|
||||
"likes": Any<Number>,
|
||||
"replies": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"edited_at": null,
|
||||
"html": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"expertise": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": "Mr Egg",
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"replies": Array [],
|
||||
"status": "hidden",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements off Hide Can hide comments 4: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "336",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements off Hide Can hide replies 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
"count": Object {
|
||||
"likes": Any<Number>,
|
||||
"replies": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"expertise": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": null,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"replies": Array [],
|
||||
"status": "published",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements off Hide Can hide replies 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "355",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements off Hide Can hide replies 3: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
"count": Object {
|
||||
"likes": Any<Number>,
|
||||
"replies": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"edited_at": null,
|
||||
"html": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"expertise": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": null,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"replies": Array [],
|
||||
"status": "hidden",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements off Hide Can hide replies 4: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "332",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements off likes Can like a comment 1: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"x-cache-invalidate": "/api/members/comments/post/618ba1ffbe2896088840a6e1/",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Hide Can hide comments 1: [body] 1`] = `
|
||||
exports[`Admin Comments API Hide Can hide comments 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
|
@ -195,7 +29,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Hide Can hide comments 2: [headers] 1`] = `
|
||||
exports[`Admin Comments API Hide Can hide comments 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -207,7 +41,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Hide Can hide comments 3: [body] 1`] = `
|
||||
exports[`Admin Comments API Hide Can hide comments 3: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
|
@ -236,7 +70,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Hide Can hide comments 4: [headers] 1`] = `
|
||||
exports[`Admin Comments API Hide Can hide comments 4: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -248,7 +82,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Hide Can hide replies 1: [body] 1`] = `
|
||||
exports[`Admin Comments API Hide Can hide replies 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
|
@ -277,7 +111,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Hide Can hide replies 2: [headers] 1`] = `
|
||||
exports[`Admin Comments API Hide Can hide replies 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -289,7 +123,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Hide Can hide replies 3: [body] 1`] = `
|
||||
exports[`Admin Comments API Hide Can hide replies 3: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
|
@ -318,7 +152,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Hide Can hide replies 4: [headers] 1`] = `
|
||||
exports[`Admin Comments API Hide Can hide replies 4: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -330,7 +164,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Logged in member gets own likes via admin api can get comment liked status by impersonating member 1: [headers] 1`] = `
|
||||
exports[`Admin Comments API Logged in member gets own likes via admin api can get comment liked status by impersonating member via admin browse route 1: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -340,7 +174,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Logged in member gets own likes via admin api can get comment liked status by impersonating member via admin browse route 1: [headers] 1`] = `
|
||||
exports[`Admin Comments API Logged in member gets own likes via admin api can get comment liked status by impersonating member via admin get by comment id read route 1: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -350,77 +184,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Logged in member gets own likes via admin api can get comment liked status by impersonating member via admin get by comment id read route 1: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"x-cache-invalidate": "/api/members/comments/post/618ba1ffbe2896088840a6e1/",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Logged in member gets own likes via admin api can get comment liked status by impersonating member via admin get by comment read route 1: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"x-cache-invalidate": "/api/members/comments/post/618ba1ffbe2896088840a6e1/",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Logged in member gets own likes via admin api can get comment liked status by impersonating member via admin get by comment replies route 1: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"x-cache-invalidate": "/api/members/comments/post/618ba1ffbe2896088840a6e1/",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Logged in member gets own likes via admin api can get comment liked status by impersonating member via admin get by comment replies route 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"x-cache-invalidate": "/api/members/comments/post/618ba1ffbe2896088840a6e1/",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Logged in member gets own likes via admin api can get comment liked status by impersonating member via admin get by comment replies route 3: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"x-cache-invalidate": "/api/members/comments/post/618ba1ffbe2896088840a6e1/, /api/members/comments/67568ca99db975825f9772a5/replies/",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on Logged in member likes via admin api can get comment liked status by impersonating member 1: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"x-cache-invalidate": "/api/members/comments/post/618ba1ffbe2896088840a6e1/",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on can get logged in member likes via admin api Can like a comment 1: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"x-cache-invalidate": "/api/members/comments/post/618ba1ffbe2896088840a6e1/",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Admin Comments API - commentImprovements on likes Can like a comment 1: [headers] 1`] = `
|
||||
exports[`Admin Comments API Logged in member gets own likes via admin api can get comment liked status by impersonating member via admin get by comment replies route 1: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -12,6 +12,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a message</p><p></p><p>New line</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -31,7 +33,7 @@ exports[`Comments API Tier-only posts Members with access Can comment on a post
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "379",
|
||||
"content-length": "428",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/comments\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
|
@ -53,6 +55,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "This is a reply",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -72,7 +76,7 @@ exports[`Comments API Tier-only posts Members with access Can reply to a comment
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "348",
|
||||
"content-length": "397",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/comments\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
|
@ -154,6 +158,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -174,6 +180,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -191,6 +199,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -222,7 +232,7 @@ exports[`Comments API when commenting enabled for all when authenticated Browsin
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "1118",
|
||||
"content-length": "1265",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -242,6 +252,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -259,6 +271,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -281,6 +295,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -310,7 +326,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can bro
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "1118",
|
||||
"content-length": "1265",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -330,6 +346,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -347,6 +365,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -369,6 +389,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -398,7 +420,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can bro
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "1118",
|
||||
"content-length": "1265",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -418,6 +440,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -438,6 +462,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -455,6 +481,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -486,7 +514,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can bro
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "1118",
|
||||
"content-length": "1265",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -506,6 +534,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a message</p><p></p><p>New line</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -525,7 +555,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can com
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "379",
|
||||
"content-length": "428",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/comments\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
|
@ -547,6 +577,8 @@ Object {
|
|||
"edited_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"html": "Updated comment",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -566,7 +598,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can edi
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "370",
|
||||
"content-length": "419",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -617,6 +649,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -636,7 +670,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can lik
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "367",
|
||||
"content-length": "416",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -666,6 +700,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -685,7 +721,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can lik
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "356",
|
||||
"content-length": "405",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -705,6 +741,8 @@ Object {
|
|||
"edited_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"html": "Illegal comment update",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -724,7 +762,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can not
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "377",
|
||||
"content-length": "426",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -814,6 +852,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -833,7 +873,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can rem
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "357",
|
||||
"content-length": "406",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -853,6 +893,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "This is a reply",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -872,7 +914,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can rep
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "348",
|
||||
"content-length": "397",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/comments\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
|
@ -894,6 +936,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "This is a reply",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -913,7 +957,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can rep
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "348",
|
||||
"content-length": "397",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/comments\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
|
@ -935,6 +979,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "This is a reply",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -954,7 +1000,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can rep
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "348",
|
||||
"content-length": "397",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/comments\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
|
@ -976,6 +1022,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "This is a reply",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -995,7 +1043,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can rep
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "348",
|
||||
"content-length": "397",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/comments\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
|
@ -1025,6 +1073,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1053,7 +1103,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can req
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "414",
|
||||
"content-length": "463",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -1072,6 +1122,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1090,6 +1142,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1108,6 +1162,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1126,6 +1182,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1144,6 +1202,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1162,6 +1222,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1180,6 +1242,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1208,7 +1272,7 @@ exports[`Comments API when commenting enabled for all when authenticated Can ret
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "2313",
|
||||
"content-length": "2656",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -1297,6 +1361,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1314,6 +1380,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1332,6 +1400,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1350,6 +1420,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -1371,7 +1443,7 @@ exports[`Comments API when commenting enabled for all when authenticated Limits
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "1308",
|
||||
"content-length": "1504",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -1379,7 +1451,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled doesn't count deleted or hidden comments in replies count 1: [body] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post doesn't count deleted or hidden comments in replies count 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
|
@ -1439,7 +1511,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled doesn't count deleted or hidden comments in replies count 2: [headers] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post doesn't count deleted or hidden comments in replies count 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -1451,7 +1523,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes deleted comments 1: [body] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes deleted comments 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [],
|
||||
"meta": Object {
|
||||
|
@ -1467,7 +1539,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes deleted comments 2: [headers] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes deleted comments 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -1479,7 +1551,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes deleted comments if all replies are hidden or deleted 1: [body] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes deleted comments if all replies are hidden or deleted 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [],
|
||||
"meta": Object {
|
||||
|
@ -1495,7 +1567,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes deleted comments if all replies are hidden or deleted 2: [headers] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes deleted comments if all replies are hidden or deleted 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -1507,7 +1579,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes deleted replies 1: [body] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes deleted replies 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
|
@ -1546,7 +1618,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes deleted replies 2: [headers] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes deleted replies 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -1558,7 +1630,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes hidden comments 1: [body] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes hidden comments 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [],
|
||||
"meta": Object {
|
||||
|
@ -1574,7 +1646,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes hidden comments 2: [headers] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes hidden comments 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -1586,7 +1658,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes hidden comments if all replies are hidden or deleted 1: [body] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes hidden comments if all replies are hidden or deleted 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [],
|
||||
"meta": Object {
|
||||
|
@ -1602,7 +1674,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes hidden comments if all replies are hidden or deleted 2: [headers] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes hidden comments if all replies are hidden or deleted 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -1614,7 +1686,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes hidden replies 1: [body] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes hidden replies 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
|
@ -1653,7 +1725,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled excludes hidden replies 2: [headers] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post excludes hidden replies 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -1665,7 +1737,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled includes deleted comments if they have published replies 1: [body] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post includes deleted comments if they have published replies 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
|
@ -1725,7 +1797,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled includes deleted comments if they have published replies 2: [headers] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post includes deleted comments if they have published replies 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -1737,7 +1809,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled includes hidden comments if they have published replies 1: [body] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post includes hidden comments if they have published replies 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
|
@ -1797,7 +1869,7 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post when commentImprovements flag is enabled includes hidden comments if they have published replies 2: [headers] 1`] = `
|
||||
exports[`Comments API when commenting enabled for all when authenticated browse by post includes hidden comments if they have published replies 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
|
@ -2030,88 +2102,6 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated replies to replies does not include in_reply_to_snippet for deleted comments 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
"count": Object {
|
||||
"likes": Any<Number>,
|
||||
"replies": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": Nullable<StringMatching>,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"expertise": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": null,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"replies": Array [],
|
||||
"status": "published",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated replies to replies does not include in_reply_to_snippet for deleted comments 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "406",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated replies to replies does not include in_reply_to_snippet for hidden comments 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
Object {
|
||||
"count": Object {
|
||||
"likes": Any<Number>,
|
||||
"replies": 0,
|
||||
},
|
||||
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
|
||||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": Nullable<StringMatching>,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
"expertise": null,
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"name": null,
|
||||
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
|
||||
},
|
||||
"replies": Array [],
|
||||
"status": "published",
|
||||
},
|
||||
],
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated replies to replies does not include in_reply_to_snippet for hidden comments 2: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "406",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
"x-powered-by": "Express",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Comments API when commenting enabled for all when authenticated replies to replies has redacted in_reply_to_snippet when referenced comment is deleted 1: [body] 1`] = `
|
||||
Object {
|
||||
"comments": Array [
|
||||
|
@ -2376,6 +2366,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -2393,6 +2385,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -2424,7 +2418,7 @@ exports[`Comments API when commenting enabled for all when not authenticated Can
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "764",
|
||||
"content-length": "862",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -2444,6 +2438,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a comment</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -2461,6 +2457,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a reply</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -2492,7 +2490,7 @@ exports[`Comments API when commenting enabled for all when not authenticated Can
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "764",
|
||||
"content-length": "862",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"vary": "Accept-Encoding",
|
||||
|
@ -2662,6 +2660,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "<p>This is a message</p><p></p><p>New line</p>",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -2681,7 +2681,7 @@ exports[`Comments API when paid only commenting Members with access Can comment
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "379",
|
||||
"content-length": "428",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/comments\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
|
@ -2703,6 +2703,8 @@ Object {
|
|||
"edited_at": null,
|
||||
"html": "This is a reply",
|
||||
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
|
||||
"in_reply_to_id": null,
|
||||
"in_reply_to_snippet": null,
|
||||
"liked": Any<Boolean>,
|
||||
"member": Object {
|
||||
"avatar_image": null,
|
||||
|
@ -2722,7 +2724,7 @@ exports[`Comments API when paid only commenting Members with access Can reply to
|
|||
Object {
|
||||
"access-control-allow-origin": "*",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "348",
|
||||
"content-length": "397",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/comments\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
|
||||
|
|
|
@ -7,7 +7,6 @@ const moment = require('moment-timezone');
|
|||
const settingsCache = require('../../../core/shared/settings-cache');
|
||||
const sinon = require('sinon');
|
||||
const DomainEvents = require('@tryghost/domain-events');
|
||||
const {mockLabsEnabled, mockLabsDisabled} = require('../../utils/e2e-framework-mock-manager');
|
||||
|
||||
let membersAgent, membersAgent2, postId, postAuthorEmail, postTitle;
|
||||
|
||||
|
@ -351,8 +350,6 @@ describe('Comments API', function () {
|
|||
beforeEach(async function () {
|
||||
mockManager.mockMail();
|
||||
|
||||
mockLabsDisabled('commentImprovements');
|
||||
|
||||
// ensure we don't have data dependencies across tests
|
||||
await dbUtils.truncate('comments');
|
||||
await dbUtils.truncate('comment_likes');
|
||||
|
@ -403,52 +400,44 @@ describe('Comments API', function () {
|
|||
]);
|
||||
});
|
||||
|
||||
describe('when commentImprovements flag is enabled', function () {
|
||||
beforeEach(function () {
|
||||
mockLabsEnabled('commentImprovements');
|
||||
it('excludes hidden comments', async function () {
|
||||
const hiddenComment = await dbFns.addComment({
|
||||
post_id: postId,
|
||||
member_id: fixtureManager.get('members', 2).id,
|
||||
html: 'This is a hidden comment',
|
||||
status: 'hidden'
|
||||
});
|
||||
|
||||
it('excludes hidden comments', async function () {
|
||||
const hiddenComment = await dbFns.addComment({
|
||||
post_id: postId,
|
||||
member_id: fixtureManager.get('members', 2).id,
|
||||
html: 'This is a hidden comment',
|
||||
status: 'hidden'
|
||||
});
|
||||
const data2 = await membersAgent
|
||||
.get(`/api/comments/post/${postId}/`)
|
||||
.expectStatus(200);
|
||||
|
||||
const data2 = await membersAgent
|
||||
.get(`/api/comments/post/${postId}/`)
|
||||
.expectStatus(200);
|
||||
// check that hiddenComment.id is not in the response
|
||||
should(data2.body.comments.map(c => c.id)).not.containEql(hiddenComment.id);
|
||||
should(data2.body.comments.length).eql(0);
|
||||
});
|
||||
|
||||
// check that hiddenComment.id is not in the response
|
||||
should(data2.body.comments.map(c => c.id)).not.containEql(hiddenComment.id);
|
||||
should(data2.body.comments.length).eql(0);
|
||||
it('excludes deleted comments', async function () {
|
||||
await dbFns.addComment({
|
||||
post_id: postId,
|
||||
member_id: fixtureManager.get('members', 2).id,
|
||||
html: 'This is a deleted comment',
|
||||
status: 'deleted'
|
||||
});
|
||||
|
||||
it('excludes deleted comments', async function () {
|
||||
// await mockManager.mockLabsEnabled('commentImprovements');
|
||||
await dbFns.addComment({
|
||||
post_id: postId,
|
||||
member_id: fixtureManager.get('members', 2).id,
|
||||
html: 'This is a deleted comment',
|
||||
status: 'deleted'
|
||||
});
|
||||
const data2 = await membersAgent
|
||||
.get(`/api/comments/post/${postId}/`)
|
||||
.expectStatus(200);
|
||||
|
||||
const data2 = await membersAgent
|
||||
.get(`/api/comments/post/${postId}/`)
|
||||
.expectStatus(200);
|
||||
|
||||
// go through all comments and check if the deleted comment is not there
|
||||
data2.body.comments.forEach((comment) => {
|
||||
should(comment.html).not.eql('This is a deleted comment');
|
||||
});
|
||||
|
||||
data2.body.comments.length.should.eql(0);
|
||||
// go through all comments and check if the deleted comment is not there
|
||||
data2.body.comments.forEach((comment) => {
|
||||
should(comment.html).not.eql('This is a deleted comment');
|
||||
});
|
||||
|
||||
data2.body.comments.length.should.eql(0);
|
||||
});
|
||||
|
||||
it('shows hidden and deleted comment where there is a reply', async function () {
|
||||
await mockManager.mockLabsEnabled('commentImprovements');
|
||||
await setupBrowseCommentsData();
|
||||
const hiddenComment = await dbFns.addComment({
|
||||
post_id: postId,
|
||||
|
@ -505,7 +494,6 @@ describe('Comments API', function () {
|
|||
});
|
||||
|
||||
it('Returns nothing if both parent and reply are hidden', async function () {
|
||||
await mockManager.mockLabsEnabled('commentImprovements');
|
||||
const hiddenComment = await dbFns.addComment({
|
||||
post_id: postId,
|
||||
member_id: fixtureManager.get('members', 0).id,
|
||||
|
@ -652,11 +640,7 @@ describe('Comments API', function () {
|
|||
should.not.exist(response.body.comments[0].unsubscribe_url);
|
||||
});
|
||||
|
||||
describe('browse by post when commentImprovements flag is enabled', function () {
|
||||
beforeEach(function () {
|
||||
mockLabsEnabled('commentImprovements');
|
||||
});
|
||||
|
||||
describe('browse by post', function () {
|
||||
it('excludes deleted comments', async function () {
|
||||
await dbFns.addComment({
|
||||
member_id: fixtureManager.get('members', 2).id,
|
||||
|
@ -913,7 +897,6 @@ describe('Comments API', function () {
|
|||
});
|
||||
|
||||
it('hidden replies are not included in the count', async function () {
|
||||
await mockManager.mockLabsEnabled('commentImprovements');
|
||||
const {parent} = await dbFns.addCommentWithReplies({
|
||||
member_id: fixtureManager.get('members', 0).id,
|
||||
replies: new Array(5).fill({
|
||||
|
@ -928,7 +911,6 @@ describe('Comments API', function () {
|
|||
});
|
||||
|
||||
it('deleted replies are not included in the count', async function () {
|
||||
await mockManager.mockLabsEnabled('commentImprovements');
|
||||
const {parent} = await dbFns.addCommentWithReplies({
|
||||
member_id: fixtureManager.get('members', 0).id,
|
||||
replies: new Array(5).fill({
|
||||
|
@ -1335,10 +1317,6 @@ describe('Comments API', function () {
|
|||
});
|
||||
|
||||
describe('replies to replies', function () {
|
||||
beforeEach(function () {
|
||||
mockLabsEnabled('commentImprovements');
|
||||
});
|
||||
|
||||
it('can browse comments with replies to replies', async function () {
|
||||
const {replies: [reply]} = await dbFns.addCommentWithReplies({
|
||||
member_id: fixtureManager.get('members', 1).id,
|
||||
|
|
|
@ -8,7 +8,6 @@ const extraAttrsUtils = require('../../../../../../../core/server/api/endpoints/
|
|||
const mappers = require('../../../../../../../core/server/api/endpoints/utils/serializers/output/mappers');
|
||||
const memberAttribution = require('../../../../../../../core/server/services/member-attribution');
|
||||
const htmlToPlaintext = require('@tryghost/html-to-plaintext');
|
||||
const labs = require('../../../../../../../core/shared/labs');
|
||||
|
||||
function createJsonModel(data) {
|
||||
return Object.assign(data, {toJSON: sinon.stub().returns(data)});
|
||||
|
@ -414,6 +413,8 @@ describe('Unit: utils/serializers/output/mappers', function () {
|
|||
data: {
|
||||
// same except the remove foo keys
|
||||
id: 'id1',
|
||||
in_reply_to_id: null,
|
||||
in_reply_to_snippet: null,
|
||||
status: 'status1',
|
||||
html: 'html1',
|
||||
created_at: 'created_at1',
|
||||
|
@ -612,11 +613,7 @@ describe('Unit: utils/serializers/output/mappers', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Comment mapper (commentImprovements flag enabled)', function () {
|
||||
beforeEach(function () {
|
||||
sinon.stub(labs, 'isSet').returns(true);
|
||||
});
|
||||
|
||||
describe('Comment mapper', function () {
|
||||
it('includes in_reply_to_snippet for published replies-to-replies', function () {
|
||||
const frame = {};
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Sluit aan by die bespreking",
|
||||
"Just now": "Sopas",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Plaaslike inwoner",
|
||||
"Member discussion": "Lidmaat bespreking",
|
||||
"Name": "Naam",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Gestuur",
|
||||
"Show": "Wys",
|
||||
"Show {{amount}} more replies": "Wys {{amount}} meer antwoorde",
|
||||
"Show {{amount}} previous comments": "Wys {{amount}} vorige kommentaar",
|
||||
"Show 1 more reply": "Wys nog 1 antwoord",
|
||||
"Show 1 previous comment": "Wys 1 vorige kommentaar",
|
||||
"Show comment": "Wys kommentaar",
|
||||
"Sign in": "Teken in",
|
||||
"Sign up now": "Sluit nou aan",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "فلان الفلانى",
|
||||
"Join the discussion": "انضم للمحادثة",
|
||||
"Just now": "الآن",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "مقيم محلى",
|
||||
"Member discussion": "مناقشة الاعضاء",
|
||||
"Name": "الاسم",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "تم الارسال",
|
||||
"Show": "اظهر",
|
||||
"Show {{amount}} more replies": "اظهر {{amount}} ردود",
|
||||
"Show {{amount}} previous comments": "اظهر {{amount}} تعليقات سابقة",
|
||||
"Show 1 more reply": "اظهر تعليق وحيد",
|
||||
"Show 1 previous comment": "اظهر التعليق السابق",
|
||||
"Show comment": "اظهر التعليق",
|
||||
"Sign in": "تسجيل الدخول",
|
||||
"Sign up now": "قم بالتسجيل الآن",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Иван Иванов",
|
||||
"Join the discussion": "Участвайте в дискусията",
|
||||
"Just now": "Току-що",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Местен жител",
|
||||
"Member discussion": "Дискусия за абонатите",
|
||||
"Name": "Име",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Изпратен",
|
||||
"Show": "Показване",
|
||||
"Show {{amount}} more replies": "Покажи още {{amount}} отговора",
|
||||
"Show {{amount}} previous comments": "Покажи {{amount}} предишни коментара",
|
||||
"Show 1 more reply": "Покажи още един отговор",
|
||||
"Show 1 previous comment": "Покажи един предишен коментар",
|
||||
"Show comment": "Покажи коментар",
|
||||
"Sign in": "Вход",
|
||||
"Sign up now": "Регистрация",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "শাহ নেওয়াজ",
|
||||
"Join the discussion": "আলোচনায় যোগ দিন",
|
||||
"Just now": "এখনই",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "স্থানীয় বাসিন্দা",
|
||||
"Member discussion": "সদস্য আলোচনা",
|
||||
"Name": "নাম",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "পাঠানো হয়েছে",
|
||||
"Show": "দেখান",
|
||||
"Show {{amount}} more replies": " আরো {{amount}}টি উত্তর দেখান",
|
||||
"Show {{amount}} previous comments": "পূর্বের {{amount}}টি মন্তব্য দেখান",
|
||||
"Show 1 more reply": "১টি আরো উত্তর দেখান",
|
||||
"Show 1 previous comment": "১টি পূর্বের মন্তব্য দেখান",
|
||||
"Show comment": "মন্তব্য দেখান",
|
||||
"Sign in": "সাইন ইন করুন",
|
||||
"Sign up now": "এখনই সাইন আপ করুন",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Vanja Larsić",
|
||||
"Join the discussion": "Pridruži se diskusiji",
|
||||
"Just now": "Upravo sada",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Lokalni stanovnik",
|
||||
"Member discussion": "Diskusija članova",
|
||||
"Name": "Ime",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Poslano",
|
||||
"Show": "Prikaži",
|
||||
"Show {{amount}} more replies": "Prikaži još {{amount}} odgovora",
|
||||
"Show {{amount}} previous comments": "Prikaži prethodnih {{amount}} komentara",
|
||||
"Show 1 more reply": "Prikaži još jedan odgovor",
|
||||
"Show 1 previous comment": "Prikaži prethodni komentar",
|
||||
"Show comment": "Prikaži komentar",
|
||||
"Sign in": "Prijavi se",
|
||||
"Sign up now": "Postani član",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Uneix-te al debat",
|
||||
"Just now": "Just ara",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Resident local",
|
||||
"Member discussion": "Debat de membres",
|
||||
"Name": "Nom",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Enviat",
|
||||
"Show": "Mostra",
|
||||
"Show {{amount}} more replies": "Mostra {{amount}} respostes més",
|
||||
"Show {{amount}} previous comments": "Mostra {{amount}} comentaris previs",
|
||||
"Show 1 more reply": "Mostra 1 resposta més",
|
||||
"Show 1 previous comment": "Mostra 1 comentari previ",
|
||||
"Show comment": "Mostra comentari",
|
||||
"Sign in": "Inicia sessió",
|
||||
"Sign up now": "Registra't ara",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Připojte se k diskusi",
|
||||
"Just now": "Právě teď",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Místní obyvatel",
|
||||
"Member discussion": "Diskuse členů",
|
||||
"Name": "Jméno",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Odesláno",
|
||||
"Show": "Zobrazit",
|
||||
"Show {{amount}} more replies": "Zobrazit {{amount}} dalších odpovědí",
|
||||
"Show {{amount}} previous comments": "Zobrazit {{amount}} předchozích komentářů",
|
||||
"Show 1 more reply": "Zobrazit 1 další odpověď",
|
||||
"Show 1 previous comment": "Zobrazit 1 předchozí komentář",
|
||||
"Show comment": "Zobrazit komentář",
|
||||
"Sign in": "Přihlásit se",
|
||||
"Sign up now": "Zaregistrujte se nyní",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Bliv en del af diskussionen",
|
||||
"Just now": "Lige nu",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Lokal borger",
|
||||
"Member discussion": "Medlemsdiskussion",
|
||||
"Name": "Navn",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Sendt",
|
||||
"Show": "Vis",
|
||||
"Show {{amount}} more replies": "Vis {{amount}} flere svar",
|
||||
"Show {{amount}} previous comments": "Vis {{amount}} tidligere kommentarer",
|
||||
"Show 1 more reply": "Vis 1 mere svar",
|
||||
"Show 1 previous comment": "Vis 1 tidligere kommentar",
|
||||
"Show comment": "Vis kommentar",
|
||||
"Sign in": "Log ind",
|
||||
"Sign up now": "Tilmed dig nu",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "{{amount}} vorherige Kommentare anzeigen",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "Einen vorherigen Kommentar anzeigen",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Nimm an der Diskussion teil",
|
||||
"Just now": "Gerade eben",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Ortsansässiger",
|
||||
"Member discussion": "Mitgliederdiskussion",
|
||||
"Name": "Name",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Gesendet",
|
||||
"Show": "Anzeigen",
|
||||
"Show {{amount}} more replies": "{{amount}} weitere Antworten anzeigen",
|
||||
"Show {{amount}} previous comments": "{{amount}} frühere Kommentare anzeigen",
|
||||
"Show 1 more reply": "1 weitere Antwort anzeigen",
|
||||
"Show 1 previous comment": "1 vorherigen Kommentar anzeigen",
|
||||
"Show comment": "Kommentar anzeigen",
|
||||
"Sign in": "Einloggen",
|
||||
"Sign up now": "Jetzt registrieren",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Τζέιμι Λάρσον",
|
||||
"Join the discussion": "Συμμετοχή στη συζήτηση",
|
||||
"Just now": "Μόλις τώρα",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Τοπικός κάτοικος",
|
||||
"Member discussion": "Συζήτηση μελών",
|
||||
"Name": "Όνομα",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Απεστάλη",
|
||||
"Show": "Εμφάνιση",
|
||||
"Show {{amount}} more replies": "Εμφάνιση {{amount}} περισσότερων απαντήσεων",
|
||||
"Show {{amount}} previous comments": "Εμφάνιση {{amount}} προηγούμενων σχολίων",
|
||||
"Show 1 more reply": "Εμφάνιση 1 ακόμα απάντησης",
|
||||
"Show 1 previous comment": "Εμφάνιση 1 προηγούμενου σχολίου",
|
||||
"Show comment": "Εμφάνιση σχολίου",
|
||||
"Sign in": "Σύνδεση",
|
||||
"Sign up now": "Εγγραφείτε τώρα",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Únete a la discusión",
|
||||
"Just now": "Justo ahora",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Residente local",
|
||||
"Member discussion": "Discusión de miembros",
|
||||
"Name": "Nombre",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Enviar",
|
||||
"Show": "Mostrar",
|
||||
"Show {{amount}} more replies": "Mostrar {{amount}} respuestas más",
|
||||
"Show {{amount}} previous comments": "Mostrar {{amount}} comentarios previos",
|
||||
"Show 1 more reply": "Mostrar 1 respuesta más",
|
||||
"Show 1 previous comment": "Mostrar 1 comentario previo",
|
||||
"Show comment": "Mostrar comentario",
|
||||
"Sign in": "Inicia sesión",
|
||||
"Sign up now": "Regístrate ahora",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Liitu aruteluga",
|
||||
"Just now": "Just praegu",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Kohalik elanik",
|
||||
"Member discussion": "Liikmete arutelu",
|
||||
"Name": "Nimi",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Saadetud",
|
||||
"Show": "Näita",
|
||||
"Show {{amount}} more replies": "Näita {{amount}} vastust veel",
|
||||
"Show {{amount}} previous comments": "Näita {{amount}} eelmist kommentaari",
|
||||
"Show 1 more reply": "Näita 1 vastus veel",
|
||||
"Show 1 previous comment": "Näita eelmist kommentaari",
|
||||
"Show comment": "Näita kommentaari",
|
||||
"Sign in": "Logi sisse",
|
||||
"Sign up now": "Registreeru nüüd",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "جیمی لارسن",
|
||||
"Join the discussion": "به گفتمان بپیوندید",
|
||||
"Just now": "پیوستن",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "ساکن محلی",
|
||||
"Member discussion": "گفتمان کاربران",
|
||||
"Name": "نام",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "ارسال شد",
|
||||
"Show": "نمایش",
|
||||
"Show {{amount}} more replies": "نمایش {{amount}} پاسخ بیشتر",
|
||||
"Show {{amount}} previous comments": "نمایش {{amount}} دیدگاه قبل\u200cتر",
|
||||
"Show 1 more reply": "نمایش یک دیدگاه بیشتر",
|
||||
"Show 1 previous comment": "نمایش یک دیدگاه قبل\u200cتر",
|
||||
"Show comment": "نمایش دیدگاه",
|
||||
"Sign in": "ورود به حساب",
|
||||
"Sign up now": "ایجاد حساب",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Liity keskusteluun",
|
||||
"Just now": "Juuri nyt",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Paikallinen",
|
||||
"Member discussion": "Jäsenten keskustelu",
|
||||
"Name": "Nimi",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Lähetetty",
|
||||
"Show": "Näytä",
|
||||
"Show {{amount}} more replies": "Näytä {{amount}} vastausta lisää ",
|
||||
"Show {{amount}} previous comments": "Näytä {{amount}} edellistä kommenttia",
|
||||
"Show 1 more reply": "Näytä 1 vastaus lisää",
|
||||
"Show 1 previous comment": "Näytä edellinen kommentti",
|
||||
"Show comment": "Näytä kommentti",
|
||||
"Sign in": "Kirjaudu sisään",
|
||||
"Sign up now": "Rekisteröidy nyt",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jean Martin",
|
||||
"Join the discussion": "Rejoindre la discussion",
|
||||
"Just now": "À l'instant",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Résident local",
|
||||
"Member discussion": "Discussion entre abonnés",
|
||||
"Name": "Nom",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Envoyé",
|
||||
"Show": "Afficher",
|
||||
"Show {{amount}} more replies": "Afficher {{amount}} réponses supplémentaires",
|
||||
"Show {{amount}} previous comments": "Afficher {{amount}} commentaires précédents",
|
||||
"Show 1 more reply": "Afficher 1 réponse supplémentaire",
|
||||
"Show 1 previous comment": "Afficher 1 commentaire précédent",
|
||||
"Show comment": "Afficher le commentaire",
|
||||
"Sign in": "Se connecter",
|
||||
"Sign up now": "S'inscrire maintenant",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Seamaidh Larson",
|
||||
"Join the discussion": "Gabh pàirt san deasbad",
|
||||
"Just now": "An-dràsta",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Neach-còmhnaidh ionadail",
|
||||
"Member discussion": "Deasbad",
|
||||
"Name": "Ainm",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Air a chur",
|
||||
"Show": "Seall",
|
||||
"Show {{amount}} more replies": "An àireamh de bheachdan a bharrachd a chìthear: {{amount}}",
|
||||
"Show {{amount}} previous comments": "An àireamh de bheachdan roimhe a chìthear: {{amount}}",
|
||||
"Show 1 more reply": "Seall beachd a bharrachd",
|
||||
"Show 1 previous comment": "Seall am beachd roimhe",
|
||||
"Show comment": "Seall am beachd",
|
||||
"Sign in": "Clàraich a-steach",
|
||||
"Sign up now": "Clàraich a-nis",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "ג׳יימי לרסון",
|
||||
"Join the discussion": "הצטרפו לדיון",
|
||||
"Just now": "ממש עכשיו",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "תושב מקומי",
|
||||
"Member discussion": "דיון חברים רשומים",
|
||||
"Name": "שם",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "שלחנו",
|
||||
"Show": "להציג",
|
||||
"Show {{amount}} more replies": "להציג עוד {{amount}} תגובות",
|
||||
"Show {{amount}} previous comments": "להציג {{amount}} תגובות קודמות",
|
||||
"Show 1 more reply": "להציג תגובה נוספת",
|
||||
"Show 1 previous comment": "להציג תגובה קודמת",
|
||||
"Show comment": "להציג תגובה",
|
||||
"Sign in": "היכנסו",
|
||||
"Sign up now": "הירשמו עכשיו",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "राहुल शर्मा",
|
||||
"Join the discussion": "चर्चा में शामिल हों",
|
||||
"Just now": "अभी",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "स्थानीय निवासी",
|
||||
"Member discussion": "सदस्य चर्चा",
|
||||
"Name": "नाम",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "भेजा गया",
|
||||
"Show": "दिखाएं",
|
||||
"Show {{amount}} more replies": "{{amount}} और जवाब दिखाएं",
|
||||
"Show {{amount}} previous comments": "{{amount}} पिछली टिप्पणियाँ दिखाएं",
|
||||
"Show 1 more reply": "1 और जवाब दिखाएं",
|
||||
"Show 1 previous comment": "1 पिछली टिप्पणी दिखाएं",
|
||||
"Show comment": "टिप्पणी दिखाएं",
|
||||
"Sign in": "साइन इन करें",
|
||||
"Sign up now": "अभी साइन अप करें",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Pridruži se raspravi",
|
||||
"Just now": "Upravo sada",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Lokalni stanovnik",
|
||||
"Member discussion": "Rasprava članova",
|
||||
"Name": "Ime",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Poslano",
|
||||
"Show": "Prikaži",
|
||||
"Show {{amount}} more replies": "Prikaži još {{amount}} odgovora",
|
||||
"Show {{amount}} previous comments": "Prikaži {{amount}} prethodnih komentara",
|
||||
"Show 1 more reply": "Prikaži još jedan odgovor",
|
||||
"Show 1 previous comment": "Prikaži prethodan komentar",
|
||||
"Show comment": "Prikaži komentar",
|
||||
"Sign in": "Prijava",
|
||||
"Sign up now": "Registriraj se sada",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Kiss Sára",
|
||||
"Join the discussion": "Csatlakozzon a beszélgetéshez",
|
||||
"Just now": "Épp most",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Helyi lakos",
|
||||
"Member discussion": "Hozzászólások",
|
||||
"Name": "Név",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Elküldve",
|
||||
"Show": "Mutat",
|
||||
"Show {{amount}} more replies": "Mutass még {{amount}} választ",
|
||||
"Show {{amount}} previous comments": "Mutass {{amount}} előző hozzászólást",
|
||||
"Show 1 more reply": "Mutass még egy választ",
|
||||
"Show 1 previous comment": "Mutass még egy hozzászólást",
|
||||
"Show comment": "Hozzászólás mutatása",
|
||||
"Sign in": "Bejelentkezés",
|
||||
"Sign up now": "Regisztráljon most",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Sutan T. Alisjahbana",
|
||||
"Join the discussion": "Bergabung dalam diskusi",
|
||||
"Just now": "Baru saja",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Penduduk lokal",
|
||||
"Member discussion": "Diskusi anggota",
|
||||
"Name": "Nama",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Terkirim",
|
||||
"Show": "Tampilkan",
|
||||
"Show {{amount}} more replies": "Tampilkan {{amount}} balasan lainnya",
|
||||
"Show {{amount}} previous comments": "Tampilkan {{amount}} komentar sebelumnya",
|
||||
"Show 1 more reply": "Tampilkan 1 balasan lainnya",
|
||||
"Show 1 previous comment": "Tampilkan 1 komentar sebelumnya",
|
||||
"Show comment": "Tampilkan komentar",
|
||||
"Sign in": "Masuk",
|
||||
"Sign up now": "Daftar sekarang",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Andrea Rossi",
|
||||
"Join the discussion": "Partecipa alla discussione",
|
||||
"Just now": "Adesso",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Paesano",
|
||||
"Member discussion": "Commenti",
|
||||
"Name": "Nome",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Inviato",
|
||||
"Show": "Mostra",
|
||||
"Show {{amount}} more replies": "Mostra altre {{amount}} risposte",
|
||||
"Show {{amount}} previous comments": "Mostra altri {{amount}} commenti",
|
||||
"Show 1 more reply": "Mostra un'altra risposta",
|
||||
"Show 1 previous comment": "Mostra un commento precedente",
|
||||
"Show comment": "Mostra commento",
|
||||
"Sign in": "Accedi",
|
||||
"Sign up now": "Accedi ora",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "ジェイミー・ラーソン",
|
||||
"Join the discussion": "議論に参加する",
|
||||
"Just now": "今すぐ参加する",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "地元住民",
|
||||
"Member discussion": "メンバーによる議論",
|
||||
"Name": "名前",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "送信完了",
|
||||
"Show": "表示する",
|
||||
"Show {{amount}} more replies": "{{amount}}個の返信を表示する",
|
||||
"Show {{amount}} previous comments": "前のコメントを{{amount}}個表示する",
|
||||
"Show 1 more reply": "返信をもう1つ表示する",
|
||||
"Show 1 previous comment": "1つ前のコメントを表示する",
|
||||
"Show comment": "コメントを表示する",
|
||||
"Sign in": "ログイン",
|
||||
"Sign up now": "今すぐ新規登録する",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "제이미 라슨",
|
||||
"Join the discussion": "댓글에 참여해 주세요",
|
||||
"Just now": "방금 전",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "지역 주민",
|
||||
"Member discussion": "회원들의 댓글",
|
||||
"Name": "이름",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "전송됨",
|
||||
"Show": "보기",
|
||||
"Show {{amount}} more replies": "{{amount}}개의 댓글 더 보기",
|
||||
"Show {{amount}} previous comments": "{{amount}}개의 이전 댓글 보기",
|
||||
"Show 1 more reply": "1개의 댓글 더 보기",
|
||||
"Show 1 previous comment": "1개의 이전 댓글 보기",
|
||||
"Show comment": "댓글 보기",
|
||||
"Sign in": "로그인",
|
||||
"Sign up now": "회원가입",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Пәленше Түгеншиев",
|
||||
"Join the discussion": "Талқыға қосылу",
|
||||
"Just now": "Дәл қазір",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Жергілікті тұрғын",
|
||||
"Member discussion": "Мүшелер талқысы",
|
||||
"Name": "Есімі",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Жіберілді",
|
||||
"Show": "Көрсету",
|
||||
"Show {{amount}} more replies": "Тағы {{amount}} жауапты көрсету",
|
||||
"Show {{amount}} previous comments": "Алдыңғы {{amount}} пікірді көрсету",
|
||||
"Show 1 more reply": "Тағы 1 жауап көрсету",
|
||||
"Show 1 previous comment": "Алдыңғы 1 пікірді көрсету",
|
||||
"Show comment": "Пікірді көрсету",
|
||||
"Sign in": "Кіру",
|
||||
"Sign up now": "Қазір тіркелу",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Vardenis Pavardenis",
|
||||
"Join the discussion": "Prisijunkite prie diskusijos",
|
||||
"Just now": "Ką tik",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Vietinis gyventojas",
|
||||
"Member discussion": "Komentarai",
|
||||
"Name": "Vardas",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Išsiųsta",
|
||||
"Show": "Rodyti",
|
||||
"Show {{amount}} more replies": "Rodyti daugiau atsakymų ({{amount}})",
|
||||
"Show {{amount}} previous comments": "Rodyti ankstesnius komentarus ({{amount}})",
|
||||
"Show 1 more reply": "Rodyti dar 1 atsakymą",
|
||||
"Show 1 previous comment": "Rodyti ankstesnį komentarą",
|
||||
"Show comment": "Rodyti komentarą",
|
||||
"Sign in": "Prisijungti",
|
||||
"Sign up now": "Registruotis",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Петар Петровски",
|
||||
"Join the discussion": "Приклучете се во разговорот",
|
||||
"Just now": "Штотуку",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Локал жител",
|
||||
"Member discussion": "Разговор на членовите",
|
||||
"Name": "Име",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Испратено",
|
||||
"Show": "Покажи",
|
||||
"Show {{amount}} more replies": "Покажи уште {{amount}} одговори",
|
||||
"Show {{amount}} previous comments": "Покажи {{amount}} претходни коментари",
|
||||
"Show 1 more reply": "Покажи уште 1 одговор",
|
||||
"Show 1 previous comment": "Покажи 1 претходен коментар",
|
||||
"Show comment": "Покажи коментар",
|
||||
"Sign in": "Најавете се",
|
||||
"Sign up now": "Регистрирајте се",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jan Jansen",
|
||||
"Join the discussion": "Doe mee aan het gesprek",
|
||||
"Just now": "Zojuist",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Lokale bewoner",
|
||||
"Member discussion": "Gesprek",
|
||||
"Name": "Naam",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Verzonden",
|
||||
"Show": "Tonen",
|
||||
"Show {{amount}} more replies": "Toon {{amount}} extra antwoorden",
|
||||
"Show {{amount}} previous comments": "Toon {{amount}} vorige reacties",
|
||||
"Show 1 more reply": "Toon nog 1 antwoord",
|
||||
"Show 1 previous comment": "Toon 1 vorige reactie",
|
||||
"Show comment": "Toon reactie",
|
||||
"Sign in": "Inloggen",
|
||||
"Sign up now": "Registreren",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Delta i diskusjonen",
|
||||
"Just now": "Akkurat nå",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Lokal innbygger",
|
||||
"Member discussion": "Medlemsdiskusjon",
|
||||
"Name": "Navn",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Sendt",
|
||||
"Show": "Vis",
|
||||
"Show {{amount}} more replies": "Vis {{amount}} flere svar",
|
||||
"Show {{amount}} previous comments": "Vis {{amount}} tidligere kommentarer",
|
||||
"Show 1 more reply": "Vis ett svar til",
|
||||
"Show 1 previous comment": "Vis én tidligere kommentar",
|
||||
"Show comment": "Vis kommentar",
|
||||
"Sign in": "Logg inn",
|
||||
"Sign up now": "Registrer deg nå",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Dołącz do dyskusji",
|
||||
"Just now": "Przed chwilą",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "Członek dyskusji",
|
||||
"Name": "Imię",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Wysłano",
|
||||
"Show": "Pokza",
|
||||
"Show {{amount}} more replies": "Pokaż {{amount}} kolejnych odpowiedzi",
|
||||
"Show {{amount}} previous comments": "Pokaż {{amount}} poprzednich komentarzy",
|
||||
"Show 1 more reply": "Pokaż następną odpowiedź",
|
||||
"Show 1 previous comment": "Pokaż poprzedni komentarz",
|
||||
"Show comment": "Pokaż komentarz",
|
||||
"Sign in": "Zaloguj się",
|
||||
"Sign up now": "Zarejestruj się",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Participe da discussão",
|
||||
"Just now": "Agora mesmo",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Residente local",
|
||||
"Member discussion": "Discussão entre membros",
|
||||
"Name": "Nome",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Enviado",
|
||||
"Show": "Mostrar",
|
||||
"Show {{amount}} more replies": "Mostrar mais {{amount}} respostas",
|
||||
"Show {{amount}} previous comments": "Mostrar {{amount}} comentários anteriores",
|
||||
"Show 1 more reply": "Mostrar 1 resposta adicional",
|
||||
"Show 1 previous comment": "Mostrar 1 comentário anterior",
|
||||
"Show comment": "Mostrar comentário",
|
||||
"Sign in": "Entrar",
|
||||
"Sign up now": "Inscreva-se agora",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jane Doe",
|
||||
"Join the discussion": "Junte-se à discussão",
|
||||
"Just now": "Agora",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Residente local",
|
||||
"Member discussion": "Discussão para membros",
|
||||
"Name": "Nome",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Enviado",
|
||||
"Show": "Mostrar",
|
||||
"Show {{amount}} more replies": "Mostrar mais {{amount}} respostas",
|
||||
"Show {{amount}} previous comments": "Mostrar os {{amount}} comentários anteriores",
|
||||
"Show 1 more reply": "Mostrar mais uma resposta",
|
||||
"Show 1 previous comment": "Mostrar mais um comentário",
|
||||
"Show comment": "Mostrar comentário",
|
||||
"Sign in": "Registar",
|
||||
"Sign up now": "Registar agora",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Alătură-te discuției",
|
||||
"Just now": "Chiar acum",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Rezident local",
|
||||
"Member discussion": "Discuție membrii",
|
||||
"Name": "Nume",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Trimis",
|
||||
"Show": "Arată",
|
||||
"Show {{amount}} more replies": "Arată încă {{amount}} răspunsuri",
|
||||
"Show {{amount}} previous comments": "Arată {{amount}} comentarii anterioare",
|
||||
"Show 1 more reply": "Arată încă un răspuns",
|
||||
"Show 1 previous comment": "Arată un comentariu anterior",
|
||||
"Show comment": "Arată comentariul",
|
||||
"Sign in": "Autentificare",
|
||||
"Sign up now": "Înregistrează-te acum",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Павел Бид",
|
||||
"Join the discussion": "Присоединиться к обсуждению",
|
||||
"Just now": "Сейчас",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Местный житель",
|
||||
"Member discussion": "Обсуждение участников",
|
||||
"Name": "Имя",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Отправлено",
|
||||
"Show": "Показать",
|
||||
"Show {{amount}} more replies": "Показать ещё {{amount}} ответа(ов)",
|
||||
"Show {{amount}} previous comments": "Показать ещё {{amount}} комментария(ев)",
|
||||
"Show 1 more reply": "Показать ответ",
|
||||
"Show 1 previous comment": "Показать предыдущий комментарий",
|
||||
"Show comment": "Показать комментарий",
|
||||
"Sign in": "Войти",
|
||||
"Sign up now": "Зарегистрироваться",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "ජේමි ලාර්සන්",
|
||||
"Join the discussion": "සාකච්ඡාවට එක්වන්න",
|
||||
"Just now": "මේ දැ\u200bන්",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "දේශීය පදිංචි",
|
||||
"Member discussion": "සාමාජික සාකච්ඡාව",
|
||||
"Name": "න\u200bම",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "යැව්වා",
|
||||
"Show": "පෙන්වන්\u200bන",
|
||||
"Show {{amount}} more replies": "තවත් පිළිතුරු {{amount}} පෙන්වන්න",
|
||||
"Show {{amount}} previous comments": "පෙර අදහස් {{amount}} පෙන්වන්න",
|
||||
"Show 1 more reply": "තවත් පිළිතුරු 1ක් පෙන්වන්න",
|
||||
"Show 1 previous comment": "පෙර අදහස් 1ක් පෙන්වන්න",
|
||||
"Show comment": "අදහස පෙන්වන්න",
|
||||
"Sign in": "Sign in වෙන්\u200bන",
|
||||
"Sign up now": "දැන්ම Sign up වෙන්\u200bන",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Zapojiť sa do diskusie",
|
||||
"Just now": "Teraz",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Miestny obyvateľ",
|
||||
"Member discussion": "",
|
||||
"Name": "Meno",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Odoslané",
|
||||
"Show": "Zobraziť",
|
||||
"Show {{amount}} more replies": "Zobraziť {{amount}} ďalších odpoveďí",
|
||||
"Show {{amount}} previous comments": "Zobraziť {{amount}} predchádzajúcich komentárov",
|
||||
"Show 1 more reply": "Zobraziť 1 ďalšiu odpoveď",
|
||||
"Show 1 previous comment": "Zobraziť 1 predchádzajúci komentár",
|
||||
"Show comment": "Zobraziť komentár",
|
||||
"Sign in": "Prihlásiť",
|
||||
"Sign up now": "Registrovať sa",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Џејми Ларсон",
|
||||
"Join the discussion": "Придружите се дискусији",
|
||||
"Just now": "Управо сада",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Мештанин",
|
||||
"Member discussion": "Дискусија чланова",
|
||||
"Name": "Име",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Послато",
|
||||
"Show": "Прикажи",
|
||||
"Show {{amount}} more replies": "Прикажи још {{amount}} одговора",
|
||||
"Show {{amount}} previous comments": "Прикажи претходна {{amount}} коментара",
|
||||
"Show 1 more reply": "Прикажи још 1 одговор",
|
||||
"Show 1 previous comment": "Прикажи 1 претходни коментар",
|
||||
"Show comment": "Прикажи коментар",
|
||||
"Sign in": "Пријавите се",
|
||||
"Sign up now": "Пријавите се сада",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Anders Andersson",
|
||||
"Join the discussion": "Var med i diskussionen",
|
||||
"Just now": "Nu precis",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Lokalboende",
|
||||
"Member discussion": "Medlemsdiskussion",
|
||||
"Name": "Namn",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Skickad",
|
||||
"Show": "Visa",
|
||||
"Show {{amount}} more replies": "Visa {{amount}} fler svar",
|
||||
"Show {{amount}} previous comments": "Visa {{amount}} tidigare kommentarer",
|
||||
"Show 1 more reply": "Visa 1 kommentar till",
|
||||
"Show 1 previous comment": "Visa 1 tidigare kommentar",
|
||||
"Show comment": "Visa kommentar",
|
||||
"Sign in": "Logga in",
|
||||
"Sign up now": "Registrera dig nu",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Jiunge na mjadala",
|
||||
"Just now": "Hivi sasa",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Mkazi wa eneo",
|
||||
"Member discussion": "Mjadala wa wanachama",
|
||||
"Name": "Jina",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Imetumwa",
|
||||
"Show": "Onyesha",
|
||||
"Show {{amount}} more replies": "Onyesha majibu {{amount}} zaidi",
|
||||
"Show {{amount}} previous comments": "Onyesha maoni {{amount}} ya awali",
|
||||
"Show 1 more reply": "Onyesha jibu 1 zaidi",
|
||||
"Show 1 previous comment": "Onyesha maoni 1 ya awali",
|
||||
"Show comment": "Onyesha maoni",
|
||||
"Sign in": "Ingia",
|
||||
"Sign up now": "Jisajili sasa",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "ஜேமி லார்சன்",
|
||||
"Join the discussion": "கலந்துரையாடலில் சேரவும்",
|
||||
"Just now": "சற்றுமுன்னர்தான்",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "உள்ளூர்வாசி",
|
||||
"Member discussion": "உறுப்பினர் கருத்து",
|
||||
"Name": "பெயர்",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "அனுப்பப்பட்டது",
|
||||
"Show": "காட்டு",
|
||||
"Show {{amount}} more replies": "முந்தைய {{amount}} மேலும் பதில்கள்க் காட்டு",
|
||||
"Show {{amount}} previous comments": "முந்தைய {{amount}} கருத்துகளைக் காட்டு",
|
||||
"Show 1 more reply": "மேலும் 1 பதிலைக் காட்டு",
|
||||
"Show 1 previous comment": "முந்தைய 1 கருத்தைக் காட்டு",
|
||||
"Show comment": "கருத்தைக் காட்டு",
|
||||
"Sign in": "உள்நுழைக",
|
||||
"Sign up now": "இப்பொழுதே பதிவு செய்யுங்கள்",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "กนกพัฒน์ สัณห์ฤทัย",
|
||||
"Join the discussion": "เข้าร่วมการสนทนา",
|
||||
"Just now": "ตอนนี้",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "ผู้อยู่อาศัยในท้องถิ่น",
|
||||
"Member discussion": "การสนทนาของสมาชิก",
|
||||
"Name": "ชื่อ",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "ส่งแล้ว",
|
||||
"Show": "แสดง",
|
||||
"Show {{amount}} more replies": "แสดง {{amount}} การตอบกลับเพิ่มเติม",
|
||||
"Show {{amount}} previous comments": "แสดง {{amount}} ความคิดเห็นก่อนหน้า",
|
||||
"Show 1 more reply": "แสดงอีก 1 การตอบกลับ",
|
||||
"Show 1 previous comment": "แสดง 1 ความคิดเห็น",
|
||||
"Show comment": "ดูความคิดเห็น",
|
||||
"Sign in": "ลงชื่อเข้าใช้",
|
||||
"Sign up now": "สมัครใช้งานตอนนี้เลย",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Ad Soyad",
|
||||
"Join the discussion": "Tartışmaya katıl",
|
||||
"Just now": "Şu anda",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Yerel sakini",
|
||||
"Member discussion": "Üye tartışması",
|
||||
"Name": "Ad",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Gönderildi",
|
||||
"Show": "Göster",
|
||||
"Show {{amount}} more replies": "{{amount}} daha fazla yanıt göster",
|
||||
"Show {{amount}} previous comments": "{{amount}} önceki yorumu göster",
|
||||
"Show 1 more reply": "1 cevap daha göster",
|
||||
"Show 1 previous comment": "1 önceki yorumu göster",
|
||||
"Show comment": "Yorumu göster",
|
||||
"Sign in": "Giriş yap",
|
||||
"Sign up now": "Şimdi kayıt ol",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Ваше імʼя",
|
||||
"Join the discussion": "Долучитися до обговорення",
|
||||
"Just now": "Прямо зараз",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Місцевий експерт",
|
||||
"Member discussion": "Обговорення учасників",
|
||||
"Name": "Імʼя",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Відправлено",
|
||||
"Show": "Показати",
|
||||
"Show {{amount}} more replies": "Показати ще {{amount}} відповідей",
|
||||
"Show {{amount}} previous comments": "Показати {{amount}} попередніх коментарів",
|
||||
"Show 1 more reply": "Показати ще одну відповідь",
|
||||
"Show 1 previous comment": "Показати один попередній коментар",
|
||||
"Show comment": "Показати коментар",
|
||||
"Sign in": "Увійти",
|
||||
"Sign up now": "Зареєструватись зараз",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "جیمی لارسن",
|
||||
"Join the discussion": "تبادلے میں شامل ہوں",
|
||||
"Just now": "ابھی",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "مقامی رہائشی",
|
||||
"Member discussion": "رکن کا تبادلہ",
|
||||
"Name": "نام",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "بھیجا گیا",
|
||||
"Show": "دکھائیں",
|
||||
"Show {{amount}} more replies": "{{amount}} مزید جوابات دکھائیں",
|
||||
"Show {{amount}} previous comments": "{{amount}} پچھلے تبادلات دکھائیں",
|
||||
"Show 1 more reply": "1 مزید جواب دکھائیں",
|
||||
"Show 1 previous comment": "1 پچھلا تبادلہ دکھائیں",
|
||||
"Show comment": "تبادلہ دکھائیں",
|
||||
"Sign in": "سائن ان کریں",
|
||||
"Sign up now": "ابھی رجسٹر ہوں",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "",
|
||||
"Join the discussion": "",
|
||||
"Just now": "",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "",
|
||||
"Member discussion": "",
|
||||
"Name": "",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "",
|
||||
"Show": "",
|
||||
"Show {{amount}} more replies": "",
|
||||
"Show {{amount}} previous comments": "",
|
||||
"Show 1 more reply": "",
|
||||
"Show 1 previous comment": "",
|
||||
"Show comment": "",
|
||||
"Sign in": "",
|
||||
"Sign up now": "",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "Tham gia thảo luận",
|
||||
"Just now": "Vừa xong",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "Cư dân địa phương",
|
||||
"Member discussion": "Thảo luận của thành viên",
|
||||
"Name": "Tên",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "Đã gửi",
|
||||
"Show": "Hiển thị",
|
||||
"Show {{amount}} more replies": "Xem {{amount}} trả lời khác",
|
||||
"Show {{amount}} previous comments": "Đọc {{amount}} bình luận trước",
|
||||
"Show 1 more reply": "Xem 1 trả lời",
|
||||
"Show 1 previous comment": "Đọc 1 bình luận trước",
|
||||
"Show comment": "Đọc bình luận",
|
||||
"Sign in": "Đăng nhập",
|
||||
"Sign up now": "Đăng ký ngay",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "加入討論",
|
||||
"Just now": "剛剛",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "本地居民",
|
||||
"Member discussion": "會員討論",
|
||||
"Name": "稱呼",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "已發送",
|
||||
"Show": "顯示",
|
||||
"Show {{amount}} more replies": "顯示後續 {{amount}} 則留言",
|
||||
"Show {{amount}} previous comments": "顯示先前 {{amount}} 則留言",
|
||||
"Show 1 more reply": "顯示下一則留言",
|
||||
"Show 1 previous comment": "顯示前一則留言",
|
||||
"Show comment": "顯示留言",
|
||||
"Sign in": "登錄",
|
||||
"Sign up now": "立即註冊",
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
"Jamie Larson": "Jamie Larson",
|
||||
"Join the discussion": "加入讨论",
|
||||
"Just now": "刚刚",
|
||||
"Load more ({{amount}})": "",
|
||||
"Local resident": "本地居民",
|
||||
"Member discussion": "会员讨论",
|
||||
"Name": "称呼",
|
||||
|
@ -55,9 +56,7 @@
|
|||
"Sent": "已发送",
|
||||
"Show": "显示",
|
||||
"Show {{amount}} more replies": "显示后续{{amount}}条评论",
|
||||
"Show {{amount}} previous comments": "显示先前{{amount}}条评论",
|
||||
"Show 1 more reply": "显示下一条评论",
|
||||
"Show 1 previous comment": "显示前一条评论",
|
||||
"Show comment": "显示评论",
|
||||
"Sign in": "登录",
|
||||
"Sign up now": "立刻注册",
|
||||
|
|
Loading…
Reference in a new issue