[single-article] Refactor class components to be functional component (#17681)
* refactor(single-article): migrates class to use pure components * test(single-article): removes repeated test from file
This commit is contained in:
parent
0960b36d92
commit
94c431afb0
2 changed files with 74 additions and 95 deletions
|
|
@ -1,8 +1,8 @@
|
|||
/* eslint-disable jest/expect-expect */
|
||||
import { h, Fragment } from 'preact';
|
||||
import { axe } from 'jest-axe';
|
||||
import { render, getNodeText, waitFor } from '@testing-library/preact';
|
||||
import { SingleArticle } from '../index';
|
||||
import '@testing-library/jest-dom';
|
||||
|
||||
const getTestArticle = () => ({
|
||||
id: 1,
|
||||
|
|
@ -39,9 +39,10 @@ describe('<SingleArticle />', () => {
|
|||
});
|
||||
|
||||
it('renders the article title', () => {
|
||||
const { queryByText } = render(
|
||||
const articleProps = getTestArticle();
|
||||
const { getByRole } = render(
|
||||
<Fragment>
|
||||
<SingleArticle {...getTestArticle()} toggleArticle={jest.fn()} />
|
||||
<SingleArticle {...articleProps} toggleArticle={jest.fn()} />
|
||||
<div
|
||||
data-testid="flag-user-modal"
|
||||
class="flag-user-modal-container hidden"
|
||||
|
|
@ -49,27 +50,13 @@ describe('<SingleArticle />', () => {
|
|||
</Fragment>,
|
||||
);
|
||||
|
||||
expect(queryByText(getTestArticle().title)).toBeDefined();
|
||||
});
|
||||
|
||||
it('renders the new clickable article title', () => {
|
||||
const { container } = render(
|
||||
<Fragment>
|
||||
<SingleArticle {...getTestArticle()} toggleArticle={jest.fn()} />
|
||||
<div
|
||||
data-testid="flag-user-modal"
|
||||
class="flag-user-modal-container hidden"
|
||||
/>
|
||||
</Fragment>,
|
||||
);
|
||||
const text = getNodeText(
|
||||
container.getElementsByClassName('article-title-heading')[0],
|
||||
);
|
||||
expect(text).toContain(getTestArticle().title);
|
||||
expect(
|
||||
getByRole('heading', { name: articleProps.title, level: 3 }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders the tags', () => {
|
||||
const { queryByText } = render(
|
||||
const { getByText } = render(
|
||||
<Fragment>
|
||||
<SingleArticle {...getTestArticle()} toggleArticle={jest.fn()} />
|
||||
<div
|
||||
|
|
@ -79,9 +66,9 @@ describe('<SingleArticle />', () => {
|
|||
</Fragment>,
|
||||
);
|
||||
|
||||
expect(queryByText('discuss')).toBeDefined();
|
||||
expect(queryByText('javascript')).toBeDefined();
|
||||
expect(queryByText('beginners')).toBeDefined();
|
||||
expect(getByText('discuss')).toBeInTheDocument();
|
||||
expect(getByText('javascript')).toBeInTheDocument();
|
||||
expect(getByText('beginners')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders no tags or # symbol when article has no tags', () => {
|
||||
|
|
@ -145,7 +132,7 @@ describe('<SingleArticle />', () => {
|
|||
});
|
||||
|
||||
it('renders the correct formatted published date', () => {
|
||||
const { queryByText } = render(
|
||||
const { getByText } = render(
|
||||
<Fragment>
|
||||
<SingleArticle {...getTestArticle()} toggleArticle={jest.fn()} />
|
||||
<div
|
||||
|
|
@ -155,7 +142,7 @@ describe('<SingleArticle />', () => {
|
|||
</Fragment>,
|
||||
);
|
||||
|
||||
expect(queryByText('Jun 22')).toBeDefined();
|
||||
expect(getByText('Jun 22')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders the correct formatted published date as a time if the date is the same day', () => {
|
||||
|
|
|
|||
|
|
@ -1,17 +1,23 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import { h, Component, Fragment } from 'preact';
|
||||
import { h, Fragment } from 'preact';
|
||||
import { createPortal } from 'preact/compat';
|
||||
import { FlagUserModal } from '../../packs/flagUserModal';
|
||||
import { formatDate } from './util';
|
||||
|
||||
export class SingleArticle extends Component {
|
||||
activateToggle = () => {
|
||||
const { id, title, path, toggleArticle } = this.props;
|
||||
export const SingleArticle = ({
|
||||
id,
|
||||
title,
|
||||
publishedAt,
|
||||
cachedTagList,
|
||||
user,
|
||||
key,
|
||||
articleOpened,
|
||||
path,
|
||||
toggleArticle,
|
||||
}) => {
|
||||
const activateToggle = () => toggleArticle(id, title, path);
|
||||
|
||||
toggleArticle(id, title, path);
|
||||
};
|
||||
|
||||
tagsFormat = (tag, key) => {
|
||||
const tagsFormat = (tag, key) => {
|
||||
if (tag) {
|
||||
return (
|
||||
<span className="crayons-tag" key={key}>
|
||||
|
|
@ -22,69 +28,55 @@ export class SingleArticle extends Component {
|
|||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
id,
|
||||
title,
|
||||
publishedAt,
|
||||
cachedTagList,
|
||||
user,
|
||||
key,
|
||||
articleOpened,
|
||||
path,
|
||||
} = this.props;
|
||||
const tags = cachedTagList.split(', ').map((tag) => {
|
||||
this.tagsFormat(tag, key);
|
||||
});
|
||||
const tags = cachedTagList.split(', ').map((tag) => tagsFormat(tag, key));
|
||||
|
||||
const newAuthorNotification = user.articles_count <= 3 ? '👋 ' : '';
|
||||
const modContainer = id
|
||||
? document.getElementById(`mod-iframe-${id}`)
|
||||
: document.getElementById('mod-container');
|
||||
const newAuthorNotification = user.articles_count <= 3 ? '👋 ' : '';
|
||||
const modContainer = id
|
||||
? document.getElementById(`mod-iframe-${id}`)
|
||||
: document.getElementById('mod-container');
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{modContainer &&
|
||||
createPortal(
|
||||
<FlagUserModal moderationUrl={path} authorId={user.id} />,
|
||||
document.getElementsByClassName('flag-user-modal-container')[0],
|
||||
)}
|
||||
<details
|
||||
id={`mod-article-${id}`}
|
||||
data-testid={`mod-article-${id}`}
|
||||
className="moderation-single-article"
|
||||
onToggle={this.activateToggle}
|
||||
>
|
||||
<summary>
|
||||
<div className="article-details-container">
|
||||
<span className="article-title">
|
||||
<header>
|
||||
<h3 className="fs-base fw-bold lh-tight article-title-heading">
|
||||
{title}
|
||||
</h3>
|
||||
</header>
|
||||
{tags}
|
||||
</span>
|
||||
<span className="article-author">
|
||||
{newAuthorNotification}
|
||||
{user.name}
|
||||
</span>
|
||||
<span className="article-published-at">
|
||||
<time dateTime={publishedAt}>{formatDate(publishedAt)}</time>
|
||||
</span>
|
||||
</div>
|
||||
</summary>
|
||||
<div
|
||||
className={`article-iframes-container${
|
||||
articleOpened ? ' opened' : ''
|
||||
}`}
|
||||
id={`article-iframe-${id}`}
|
||||
/>
|
||||
</details>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Fragment>
|
||||
{modContainer &&
|
||||
createPortal(
|
||||
<FlagUserModal moderationUrl={path} authorId={user.id} />,
|
||||
document.getElementsByClassName('flag-user-modal-container')[0],
|
||||
)}
|
||||
<details
|
||||
id={`mod-article-${id}`}
|
||||
data-testid={`mod-article-${id}`}
|
||||
className="moderation-single-article"
|
||||
onToggle={activateToggle}
|
||||
>
|
||||
<summary>
|
||||
<div className="article-details-container">
|
||||
<span className="article-title">
|
||||
<header>
|
||||
<h3 className="fs-base fw-bold lh-tight article-title-heading">
|
||||
{title}
|
||||
</h3>
|
||||
</header>
|
||||
{tags}
|
||||
</span>
|
||||
<span className="article-author">
|
||||
{newAuthorNotification}
|
||||
{user.name}
|
||||
</span>
|
||||
<span className="article-published-at">
|
||||
<time dateTime={publishedAt}>{formatDate(publishedAt)}</time>
|
||||
</span>
|
||||
</div>
|
||||
</summary>
|
||||
<div
|
||||
className={`article-iframes-container${
|
||||
articleOpened ? ' opened' : ''
|
||||
}`}
|
||||
id={`article-iframe-${id}`}
|
||||
/>
|
||||
</details>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
SingleArticle.propTypes = {
|
||||
id: PropTypes.number.isRequired,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue