Some frontend testing cleanup. (#8902)

This commit is contained in:
Nick Taylor 2020-06-25 09:07:34 -04:00 committed by GitHub
parent 32ad7aa6d4
commit 5bdbc0480d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 209 additions and 158 deletions

View file

@ -26,7 +26,10 @@ describe('<Search />', () => {
it('should have a search textbox', () => {
const { getByLabelText } = render(<Search />);
getByLabelText(/search/i);
const searchInput = getByLabelText(/search/i);
expect(searchInput.getAttribute('placeholder')).toEqual('Search...');
expect(searchInput.getAttribute('autocomplete')).toEqual('off');
});
it('should contain text the user entered in the search textbox', async () => {

View file

@ -35,13 +35,16 @@ function titleArea(previewResponse, articleState, errors) {
return (
<header className="crayons-article__header">
{coverImage.length > 0 && (
<div data-testid="article-form__cover" className="crayons-article__cover">
<div
data-testid="article-form__cover"
className="crayons-article__cover"
>
<img
className="crayons-article__cover__image"
src={coverImage}
width="1000"
height="420"
alt=""
alt="Post preview cover"
/>
</div>
)}

View file

@ -105,6 +105,11 @@ describe('<ArticleCoverImage />', () => {
/>,
);
const inputEl = getByLabelText('Change');
// Check the input validation settings
expect(inputEl.getAttribute('accept')).toEqual('image/*');
expect(Number(inputEl.dataset.maxFileSizeMb)).toEqual(25);
const file = new File(['(⌐□_□)'], 'chucknorris.png', {
type: 'image/png',
});

View file

@ -9,13 +9,11 @@ global.fetch = fetch;
describe('<ImageUploader />', () => {
const fakeLinksResponse = JSON.stringify({
"links": [
"/i/fake-link.jpg"
]
links: ['/i/fake-link.jpg'],
});
const fakeErrorMessage = {
message: "Some Fake Error"
message: 'Some Fake Error',
};
it('should have no a11y violations', async () => {
@ -25,46 +23,53 @@ describe('<ImageUploader />', () => {
});
it('displays an upload input', () => {
const { getByTestId, getByLabelText } = render(<ImageUploader />);
const { getByLabelText } = render(<ImageUploader />);
const uploadInput = getByLabelText(/Upload an image/i);
expect(uploadInput.getAttribute('type')).toEqual('file');
});
it('displays text to copy after upload', async () => {
const { getByTitle, getByTestId, getByDisplayValue, getByLabelText } = render(<ImageUploader />)
const inputEl = getByLabelText(/Upload an image/i);
const file = new File(['(⌐□_□)'], 'chucknorris.png', {
type: 'image/png',
})
fetch.mockResponse(fakeLinksResponse);
fireEvent.change(inputEl, {target: {files: [file]}});
expect(inputEl.files[0]).toEqual(file);
expect(inputEl.files).toHaveLength(1);
await waitForElement(() =>
getByTitle(/copy markdown for image/i),
const { getByTitle, getByDisplayValue, getByLabelText } = render(
<ImageUploader />,
);
getByDisplayValue(/fake-link.jpg/i);
});
// TODO: 'Copied!' is always in the DOM, and so we cannot test that the visual implications of the copy when clicking on the copy icon
it('displays an error when one occurs', async () => {
const error = 'Some error message';
const { getByTitle, getByTestId, getByDisplayValue, getByText, getByLabelText } = render(<ImageUploader />)
const inputEl = getByLabelText(/Upload an image/i);
const file = new File(['(⌐□_□)'], 'chucknorris.png', {
type: 'image/png',
});
fetch.mockReject(fakeErrorMessage);
fireEvent.change(inputEl, {target: {files: [file]}});
fetch.mockResponse(fakeLinksResponse);
fireEvent.change(inputEl, { target: { files: [file] } });
await waitForElement(() =>
getByText(/some fake error/i)
);
expect(inputEl.files[0]).toEqual(file);
expect(inputEl.files).toHaveLength(1);
await waitForElement(() => getByTitle(/copy markdown for image/i));
getByDisplayValue(/fake-link.jpg/i);
});
// TODO: 'Copied!' is always in the DOM, and so we cannot test that the visual implications of the copy when clicking on the copy icon
it('displays an error when one occurs', async () => {
const { getByText, getByLabelText } = render(<ImageUploader />);
const inputEl = getByLabelText(/Upload an image/i);
// Check the input validation settings
expect(inputEl.getAttribute('accept')).toEqual('image/*');
expect(Number(inputEl.dataset.maxFileSizeMb)).toEqual(25);
const file = new File(['(⌐□_□)'], 'chucknorris.png', {
type: 'image/png',
});
fetch.mockReject(fakeErrorMessage);
fireEvent.change(inputEl, {
target: {
files: [file],
},
});
await waitForElement(() => getByText(/some fake error/i));
});
});

View file

@ -60,7 +60,7 @@ describe('<Options />', () => {
const passedData = getPassedData();
passedData.published = true;
const { getByTestId, getByText } = render(
const { queryByTestId, getByText } = render(
<Options
passedData={passedData}
onConfigChange={null}
@ -70,9 +70,10 @@ describe('<Options />', () => {
/>,
);
getByTestId('options__danger-zone');
getByText(/danger zone/i);
getByText(/unpublish post/i);
expect(queryByTestId('options__danger-zone')).toBeDefined();
expect(getByText(/danger zone/i)).toBeDefined();
expect(getByText(/unpublish post/i)).toBeDefined();
expect(getByText(/done/i)).toBeDefined();
});
it('unpublishes an article when the unpublish post button is clicked', () => {

View file

@ -7,67 +7,70 @@ import { Preview } from '../Preview';
const doc = new JSDOM('<!doctype html><html><body></body></html>');
global.document = doc;
global.window = doc.defaultView;
global.window.currentUser = {
global.window.currentUser = Object.freeze({
id: 1,
name: 'Guy Fieri',
username: 'guyfieri',
profile_image_90:
'/uploads/user/profile_image/41/0841dbe2-208c-4daa-b498-b2f01f3d37b2.png',
};
});
let previewResponse;
let articleState;
let errors;
function getPreviewResponse() {
return {
processed_html:
'<p>My Awesome Post! Not very long, but still very awesome.</p>↵↵',
title: 'My Awesome Post',
tags: null,
cover_image: 'http://lorempixel.com/400/200/',
};
}
function getArticleState() {
return {
id: null,
title: 'My Awesome Post',
tagList: 'javascript, career, ',
description: 'Some description',
canonicalUrl: '',
series: '',
allSeries: ['Learn Something new a day'],
bodyMarkdown:
'---↵title: My Awesome Post↵published: false↵description: ↵tags: ↵---↵↵My Awesome Post Not very long, but still very awesome! ↵',
submitting: false,
editing: false,
mainImage: '/i/9ca8kb1cu34mobypm5yx.png',
organizations: [
{
id: 4,
bg_color_hex: '',
name: 'DEV',
text_color_hex: '',
profile_image_90:
'/uploads/organization/profile_image/4/1689e7ae-6306-43cd-acba-8bde7ed80a17.JPG',
},
],
organizationId: null,
errors: null,
edited: true,
updatedAt: null,
version: 'v2',
helpFor: null,
helpPosition: null,
};
}
describe('<Preview />', () => {
beforeEach(() => {
previewResponse = {
processed_html:
'<p>My Awesome Post! Not very long, but still very awesome.</p>↵↵',
title: 'My Awesome Post',
tags: null,
cover_image: 'http://lorempixel.com/400/200/',
};
articleState = {
id: null,
title: 'My Awesome Post',
tagList: 'javascript, career, ',
description: 'Some description',
canonicalUrl: '',
series: '',
allSeries: ['Learn Something new a day'],
bodyMarkdown:
'---↵title: My Awesome Post↵published: false↵description: ↵tags: ↵---↵↵My Awesome Post Not very long, but still very awesome! ↵',
submitting: false,
editing: false,
mainImage: '/i/9ca8kb1cu34mobypm5yx.png',
organizations: [
{
id: 4,
bg_color_hex: '',
name: 'DEV',
text_color_hex: '',
profile_image_90:
'/uploads/organization/profile_image/4/1689e7ae-6306-43cd-acba-8bde7ed80a17.JPG',
},
],
organizationId: null,
errors: null,
edited: true,
updatedAt: null,
version: 'v2',
helpFor: null,
helpPosition: null,
};
errors = null;
});
it('should have no a11y violations', async () => {
const { container } = render(
<Preview
previewResponse={previewResponse}
articleState={articleState}
previewResponse={getPreviewResponse()}
articleState={getArticleState()}
errors={errors}
/>,
);
@ -77,46 +80,50 @@ describe('<Preview />', () => {
});
it('shows the correct title', () => {
const { getByText } = render(
const previewResponse = getPreviewResponse();
const { queryByText } = render(
<Preview
previewResponse={previewResponse}
articleState={articleState}
articleState={getArticleState()}
errors={errors}
/>,
);
getByText(previewResponse.title);
expect(queryByText(previewResponse.title)).toBeDefined();
});
it('shows the correct tags', () => {
const { getByText } = render(
const { queryByText } = render(
<Preview
previewResponse={previewResponse}
articleState={articleState}
previewResponse={getPreviewResponse()}
articleState={getArticleState()}
errors={errors}
/>,
);
getByText(`javascript`);
getByText(`career`);
expect(queryByText(`javascript`)).toBeDefined();
expect(queryByText(`career`)).toBeDefined();
});
it('shows a cover image in the preview if one exists', () => {
const { getByTestId } = render(
const articleState = { ...getArticleState(), previewShowing: true };
const { getByTestId, getByAltText } = render(
<Preview
previewResponse={previewResponse}
previewResponse={getPreviewResponse()}
articleState={articleState}
errors={errors}
/>,
);
const coverImage = getByAltText(/post preview cover/i);
getByTestId('article-form__cover');
expect(coverImage.src).toEqual('http://lorempixel.com/400/200/');
});
it('does not show a cover image in the preview if one does not exist', () => {
previewResponse.cover_image = null;
articleState.mainImage = null;
const articleState = { ...getArticleState(), mainImage: null };
const previewResponse = { ...getPreviewResponse(), cover_image: null };
const { queryByTestId } = render(
<Preview
previewResponse={previewResponse}

View file

@ -14,11 +14,12 @@ describe('<Tabs />', () => {
});
it('renders two buttons', () => {
const { getByText } = render(
const { queryByText } = render(
<Tabs onPreview={null} previewShowing={false} />,
);
getByText(/preview/i, { selector: 'button' });
getByText(/edit/i, { selector: 'button' });
expect(queryByText(/preview/i, { selector: 'button' })).toBeDefined();
expect(queryByText(/edit/i, { selector: 'button' })).toBeDefined();
});
describe('highlights the current tab', () => {
@ -31,15 +32,15 @@ describe('<Tabs />', () => {
getByText(/preview/i, { selector: 'button' }).classList.contains(
`crayons-tabs__item--current`,
),
).toBe(true);
).toEqual(true);
expect(
getByText(/edit/i, { selector: 'button' }).classList.contains(
`crayons-tabs__item--current`,
),
).toBe(false);
).toEqual(false);
});
it('when edit is selected', () => {
it('should make the edit button the current button when not in preview mode', () => {
const { getByText } = render(
<Tabs onPreview={null} previewShowing={false} />,
);
@ -48,12 +49,29 @@ describe('<Tabs />', () => {
getByText(/edit/i, { selector: 'button' }).classList.contains(
`crayons-tabs__item--current`,
),
).toBe(true);
).toEqual(true);
expect(
getByText(/preview/i, { selector: 'button' }).classList.contains(
`crayons-tabs__item--current`,
),
).toBe(false);
).toEqual(false);
});
it('should make the preview button the current button when in preview mode', () => {
const { getByText } = render(
<Tabs onPreview={null} previewShowing={true} />,
);
expect(
getByText(/edit/i, { selector: 'button' }).classList.contains(
`crayons-tabs__item--current`,
),
).toEqual(false);
expect(
getByText(/preview/i, { selector: 'button' }).classList.contains(
`crayons-tabs__item--current`,
),
).toEqual(true);
});
});
});

View file

@ -18,13 +18,16 @@ describe('<Title />', () => {
});
it('renders the textarea', () => {
const { getByPlaceholderText } = render(
const { queryByPlaceholderText } = render(
<Title
defaultValue="Test title"
onChange={null}
switchHelpContext={null}
/>,
);
getByPlaceholderText(/post title/i, { selector: 'textarea' });
expect(
queryByPlaceholderText(/post title/i, { selector: 'textarea' }),
).toBeDefined();
});
});

View file

@ -54,7 +54,7 @@ describe('<Article /> component', () => {
});
it('should render a standard article', () => {
const { getByTestId, getByAltText } = render(
const { queryByTestId, queryByAltText } = render(
<Article
{...commonProps}
isBookmarked={false}
@ -63,12 +63,12 @@ describe('<Article /> component', () => {
/>,
);
getByTestId('article-62407');
getByAltText('Emil99 profile');
expect(queryByTestId('article-62407')).toBeDefined();
expect(queryByAltText('Emil99 profile')).toBeDefined();
});
it('should render a featured article', () => {
const { getByTestId, getByAltText } = render(
const { queryByTestId, queryByAltText } = render(
<Article
{...commonProps}
isBookmarked={false}
@ -78,8 +78,8 @@ describe('<Article /> component', () => {
/>,
);
getByTestId('featured-article');
getByAltText('Emil99 profile');
expect(queryByTestId('featured-article')).toBeDefined();
expect(queryByAltText('Emil99 profile')).toBeDefined();
});
it('should render a rich feed', () => {
@ -97,7 +97,7 @@ describe('<Article /> component', () => {
});
it('should render a featured article for an organization', () => {
const { getByTestId, getByAltText } = render(
const { queryByTestId, queryByAltText } = render(
<Article
{...commonProps}
isBookmarked={false}
@ -107,13 +107,13 @@ describe('<Article /> component', () => {
/>,
);
getByTestId('featured-article');
getByAltText('Web info-mediaries logo');
getByAltText('Emil99 profile');
expect(queryByTestId('featured-article')).toBeDefined();
expect(queryByAltText('Web info-mediaries logo')).toBeDefined();
expect(queryByAltText('Emil99 profile')).toBeDefined();
});
it('should render a featured article for a video post', () => {
const { getByTitle } = render(
const { queryByTitle } = render(
<Article
{...commonProps}
isBookmarked={false}
@ -123,7 +123,7 @@ describe('<Article /> component', () => {
/>,
);
getByTitle(/video duration/i);
expect(queryByTitle(/video duration/i)).toBeDefined();
});
it('should render with an organization', () => {
@ -191,31 +191,31 @@ describe('<Article /> component', () => {
});
it('should render with an add comment button when there are no comments', () => {
const { getByTestId } = render(
const { queryByTestId } = render(
<Article {...commonProps} isBookmarked={false} article={article} />,
);
getByTestId('add-a-comment');
expect(queryByTestId('add-a-comment')).toBeDefined();
});
it('should render as saved on reading list', () => {
const { getByText } = render(
const { queryByText } = render(
<Article {...commonProps} isBookmarked article={articleWithComments} />,
);
getByText('Saved', { selector: 'button' });
expect(queryByText('Saved', { selector: 'button' })).toBeDefined();
});
it('should render as not saved on reading list', () => {
const { getByText } = render(
const { queryByText } = render(
<Article {...commonProps} isBookmarked={false} article={article} />,
);
getByText('Save', { selector: 'button' });
expect(queryByText('Save', { selector: 'button' })).toBeDefined();
});
it('should render a video article', () => {
const { getByTitle } = render(
const { queryByTitle } = render(
<Article
{...commonProps}
isBookmarked={false}
@ -224,11 +224,11 @@ describe('<Article /> component', () => {
/>,
);
getByTitle(/video duration/i);
expect(queryByTitle(/video duration/i)).toBeDefined();
});
it('should render a podcast article', () => {
const { getByAltText, getByText } = render(
const { queryByAltText, queryByText } = render(
<Article
{...commonProps}
isBookmarked={false}
@ -236,21 +236,21 @@ describe('<Article /> component', () => {
/>,
);
getByAltText('Rubber local');
getByText('podcast', { selector: 'span' });
expect(queryByAltText('Rubber local')).toBeDefined();
expect(queryByText('podcast', { selector: 'span' })).toBeDefined();
});
it('should render a podcast episode', () => {
const { getByText } = render(
const { queryByText } = render(
<Article isBookmarked={false} article={podcastEpisodeArticle} />,
);
getByText('podcast', { selector: 'span' });
expect(queryByText('podcast', { selector: 'span' })).toBeDefined();
});
it('should render a user article', () => {
const { getByText } = render(<Article article={userArticle} />);
const { queryByText } = render(<Article article={userArticle} />);
getByText('person', { selector: 'span' });
expect(queryByText('person', { selector: 'span' })).toBeDefined();
});
});

View file

@ -12,8 +12,8 @@ describe('<LoadingArticle />', () => {
});
it('should render', () => {
const { getByTitle } = render(<LoadingArticle />);
const { queryByTitle } = render(<LoadingArticle />);
getByTitle('Loading posts...');
expect(queryByTitle('Loading posts...')).toBeDefined();
});
});

View file

@ -68,7 +68,7 @@ describe('<CommentsList />', () => {
});
it('should render "See all comments" button when there are two top comments and more than two total', () => {
const { getByTestId } = render(
const { queryByTestId } = render(
<CommentsList
comments={[singleComment, singleComment]}
articlePath=""
@ -76,6 +76,6 @@ describe('<CommentsList />', () => {
/>,
);
getByTestId('see-all-comments');
expect(queryByTestId('see-all-comments')).toBeDefined();
});
});

View file

@ -63,14 +63,14 @@ describe('<ActiveMembershipsSection />', () => {
activeMemberships,
currentMembershipRole,
} = getEmptyMembershipData();
const { getByText } = render(
const { queryByText } = render(
<ActiveMembershipsSection
activeMemberships={activeMemberships}
currentMembershipRole={currentMembershipRole}
/>,
);
getByText('Members');
expect(queryByText).toBeDefined();
});
it('should not render the membership list', () => {

View file

@ -12,9 +12,9 @@ describe('<Alert />', () => {
});
it('should render an alert', () => {
const { getByRole } = render(<Alert showAlert />);
const { queryByRole } = render(<Alert showAlert />);
getByRole('alert');
expect(queryByRole('alert')).toBeDefined();
});
it('should not render an alert', () => {

View file

@ -23,8 +23,8 @@ describe('<Article />', () => {
});
it('should render', async () => {
const { getByTitle } = render(<Article resource={getArticle()} />);
const { queryByTitle } = render(<Article resource={getArticle()} />);
getByTitle('Your approval means nothing to me');
expect(queryByTitle('Your approval means nothing to me')).toBeDefined();
});
});

View file

@ -24,16 +24,18 @@ describe('<ChannelRequest />', () => {
});
it('should render', () => {
const { getByText, getByAltText } = render(
const { queryByText, queryByAltText } = render(
<ChannelRequest resource={getResource()} />,
);
getByText('Hey Sarthak !');
getByText(
'You are not a member of this group yet. Send a request to join.',
);
getByAltText('sarthak9 profile');
getByAltText('IronMan profile');
getByText('Join IronMan', { selector: 'button' });
expect(queryByText('Hey Sarthak !')).toBeDefined();
expect(
queryByText(
'You are not a member of this group yet. Send a request to join.',
),
).toBeDefined();
expect(queryByAltText('sarthak9 profile')).toBeDefined();
expect(queryByAltText('IronMan profile')).toBeDefined();
expect(queryByText('Join IronMan', { selector: 'button' })).toBeDefined();
});
});

View file

@ -139,11 +139,11 @@ describe('<Channels />', () => {
});
it('should have the proper elements, attributes, and content', () => {
const { getByTestId } = render(getChannels(false, fakeChannels));
const { queryByTestId } = render(getChannels(false, fakeChannels));
// should have group names but no user names
// TODO: I don't understand the comment above. To revisit.
getByTestId('chat-channels-list');
expect(queryByTestId('chat-channels-list')).toBeDefined();
});
});

View file

@ -18,7 +18,7 @@ describe('<ChannelDescriptionSection />', () => {
});
it('should render', () => {
const { getByText } = render(
const { queryByText } = render(
<ChannelDescriptionSection
channelName="some name"
channelDescription="some description"
@ -26,8 +26,8 @@ describe('<ChannelDescriptionSection />', () => {
/>,
);
getByText('some name');
getByText('some description');
getByText('You are a channel member');
expect(queryByText('some name')).toBeDefined();
expect(queryByText('some description')).toBeDefined();
expect(queryByText('You are a channel member')).toBeDefined();
});
});

View file

@ -6,6 +6,10 @@ import { podcastArticle } from '../../articles/__tests__/utilities/articleUtilit
import { TodaysPodcasts } from '../TodaysPodcasts';
describe('<TodaysPodcasts /> component', () => {
beforeEach(() => {
global.filterXSS = jest.fn();
});
it('should have no a11y violations', async () => {
const { container } = render(
<TodaysPodcasts>