docbrown/app/javascript/articles/__tests__/Feed.test.jsx
Anna Buianova b3c993410b
Rename display ads vars in the views (#19877)
* Renamed display_ads vars to billboards

* Rename local vars in the feed view

* Renamed display-ad in the comment

Co-authored-by: Rajat Talesra <rajattalesra4914@gmail.com>

* Renamed variables in the views

---------

Co-authored-by: Rajat Talesra <rajattalesra4914@gmail.com>
2023-08-03 13:28:23 +03:00

300 lines
11 KiB
JavaScript

/* eslint-disable no-irregular-whitespace */
import { h } from 'preact';
import { render, waitFor } from '@testing-library/preact';
import fetch from 'jest-fetch-mock';
import '@testing-library/jest-dom';
import { Feed } from '../Feed';
import {
feedPosts,
feedPostsWherePinnedAndImagePostsSame,
firstBillboard,
secondBillboard,
thirdBillboard,
podcastEpisodes,
} from './utilities/feedUtilities';
import '../../../assets/javascripts/lib/xss';
import '../../../assets/javascripts/utilities/timeAgo';
global.fetch = fetch;
describe('<Feed /> component', () => {
const getUserData = () => {
return {
followed_tag_names: ['javascript'],
followed_podcast_ids: [1], //should we make this dynamic
profile_image_90: 'mock_url_link',
name: 'firstname lastname',
username: 'username',
reading_list_ids: [],
};
};
beforeAll(() => {
global.userData = jest.fn(() => getUserData());
document.body.setAttribute('data-user', JSON.stringify(getUserData()));
const node = document.createElement('div');
node.setAttribute('id', 'followed-podcasts');
node.setAttribute('data-episodes', JSON.stringify(podcastEpisodes));
document.body.appendChild(node);
});
describe('feedItem organization', () => {
let callback;
beforeAll(() => {
fetch.mockResponseOnce(JSON.stringify(feedPosts), {
headers: { 'content-type': 'application/json' },
});
fetch.mockResponseOnce(firstBillboard, {
headers: { 'content-type': 'text/html' },
});
fetch.mockResponseOnce(secondBillboard, {
headers: { 'content-type': 'text/html' },
});
fetch.mockResponseOnce(thirdBillboard, {
headers: { 'content-type': 'text/html' },
});
callback = jest.fn();
render(<Feed timeFrame="" renderFeed={callback} />);
});
it('should return the correct length of feedItems', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
expect(lastCallbackResult.feedItems.length).toEqual(14);
});
});
it('should set the pinnedItem and place it correctly in the feed', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
const firstPinnedItem = feedPosts.find((o) => o.pinned === true);
expect(lastCallbackResult.pinnedItem).toEqual(firstPinnedItem);
expect(lastCallbackResult.feedItems[1]).toEqual(firstPinnedItem);
});
});
it('should set the imageItem and place it correctly in the feed', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
const firstImageItem = feedPosts.find(
(post) => post.main_image !== null,
);
expect(lastCallbackResult.imageItem).toEqual(firstImageItem);
expect(lastCallbackResult.feedItems[2]).toEqual(firstImageItem);
});
});
it('should place the billboards correctly within the feedItems', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
expect(lastCallbackResult.feedItems[0]).toEqual(firstBillboard);
expect(lastCallbackResult.feedItems[3]).toEqual(secondBillboard);
expect(lastCallbackResult.feedItems[9]).toEqual(thirdBillboard);
});
});
it('should place the podcasts correctly within feedItems', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
expect(lastCallbackResult.feedItems[4]).toEqual(podcastEpisodes);
});
});
});
describe('when pinned and image posts are the same', () => {
let callback;
beforeAll(() => {
fetch.mockResponseOnce(
JSON.stringify(feedPostsWherePinnedAndImagePostsSame),
{ headers: { 'content-type': 'application/json' } },
);
fetch.mockResponseOnce(firstBillboard, {
headers: { 'content-type': 'text/html' },
});
fetch.mockResponseOnce(secondBillboard, {
headers: { 'content-type': 'text/html' },
});
fetch.mockResponseOnce(thirdBillboard, {
headers: { 'content-type': 'text/html' },
});
callback = jest.fn();
render(<Feed timeFrame="" renderFeed={callback} />);
});
it('should not set a pinned item', async () => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
const postAndImageItem = feedPostsWherePinnedAndImagePostsSame.find(
(post) => post.main_image !== null && post.pinned === true,
);
expect(lastCallbackResult.pinnedItem).toEqual(null);
expect(lastCallbackResult.imageItem).toEqual(postAndImageItem);
expect(lastCallbackResult.feedItems[1]).toEqual(postAndImageItem);
expect(lastCallbackResult.feedItems[2]).not.toEqual(postAndImageItem);
});
});
describe("when the timeframe prop is 'latest'", () => {
let callback;
beforeAll(() => {
fetch.mockResponseOnce(JSON.stringify(feedPosts), {
headers: { 'content-type': 'application/json' },
});
fetch.mockResponseOnce(firstBillboard, {
headers: { 'content-type': 'text/html' },
});
fetch.mockResponseOnce(secondBillboard, {
headers: { 'content-type': 'text/html' },
});
fetch.mockResponseOnce(thirdBillboard, {
headers: { 'content-type': 'text/html' },
});
callback = jest.fn();
render(<Feed timeFrame="latest" renderFeed={callback} />);
});
it('should not set the pinned items', async () => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
expect(lastCallbackResult.pinnedItem).toEqual(null);
});
it('should return the correct length of feedItems (by excluding pinned item)', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
expect(lastCallbackResult.feedItems.length).toEqual(13);
});
});
});
describe("when we there isn't all three billboards on the home feed", () => {
describe("when there isn't a feed_second billboard", () => {
let callback;
beforeAll(() => {
fetch.mockResponseOnce(JSON.stringify(feedPosts), {
headers: { 'content-type': 'application/json' },
});
fetch.mockResponseOnce(firstBillboard, {
headers: { 'content-type': 'text/html' },
});
fetch.mockResponseOnce(undefined);
fetch.mockResponseOnce(thirdBillboard, {
headers: { 'content-type': 'text/html' },
});
callback = jest.fn();
render(<Feed timeFrame="" renderFeed={callback} />);
});
it('should return the correct length of feedItems', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
expect(lastCallbackResult.feedItems.length).toEqual(13);
});
});
it('should still amend the organization of the feedItems correctly', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
expect(lastCallbackResult.feedItems[0]).toEqual(firstBillboard);
// there is no second billboard so podcasts get rendered in 4th place
expect(lastCallbackResult.feedItems[3]).toEqual(podcastEpisodes);
expect(lastCallbackResult.feedItems[8]).toEqual(thirdBillboard);
});
});
});
describe("when there isn't a feed_first or feed_second billboard", () => {
let callback;
beforeAll(() => {
fetch.mockResponseOnce(JSON.stringify(feedPosts), {
headers: { 'content-type': 'application/json' },
});
fetch.mockResponseOnce(undefined);
fetch.mockResponseOnce(undefined);
fetch.mockResponseOnce(thirdBillboard, {
headers: { 'content-type': 'text/html' },
});
callback = jest.fn();
render(<Feed timeFrame="" renderFeed={callback} />);
});
it('should return the correct length of feedItems', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
expect(lastCallbackResult.feedItems.length).toEqual(12);
});
});
it('should still amend the organization of the feedItems correctly', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
const pinnedItem = feedPosts.find((o) => o.pinned === true);
// there is no first billboard
expect(lastCallbackResult.feedItems[0]).toEqual(pinnedItem);
// there is no second billboard so podcasts get rendered in 3rd place
expect(lastCallbackResult.feedItems[2]).toEqual(podcastEpisodes);
expect(lastCallbackResult.feedItems[7]).toEqual(thirdBillboard);
});
});
});
describe('when items that we fetch for the feed throw an error', () => {
const callback = jest.fn();
beforeAll(() => {
global.Honeybadger = { notify: jest.fn() };
fetch.mockResponseOnce(JSON.stringify(feedPosts), {
headers: { 'content-type': 'application/json' },
});
fetch.mockRejectOnce();
fetch.mockRejectOnce();
fetch.mockResponseOnce(thirdBillboard, {
headers: { 'content-type': 'text/html' },
});
render(<Feed timeFrame="" renderFeed={callback} />);
});
it('should render and return the other feedItems', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
expect(lastCallbackResult.feedItems.length).toEqual(12);
});
});
it('should organize the feedItems correctly', async () => {
await waitFor(() => {
const lastCallbackResult =
callback.mock.calls[callback.mock.calls.length - 1][0];
const pinnedItem = feedPosts.find((o) => o.pinned === true);
// we will not be rendering the first billboard since it errored
expect(lastCallbackResult.feedItems[0]).toEqual(pinnedItem);
// we will not be rendering the second billboard since it errored
// so podcasts get rendered in 3rd place
expect(lastCallbackResult.feedItems[2]).toEqual(podcastEpisodes);
expect(lastCallbackResult.feedItems[7]).toEqual(thirdBillboard);
});
});
});
});
});