Skip to content

Commit eab0405

Browse files
feat(tag): implement articles search by tag
- Create actions for searching by tag - Create components for filtered articles page - Write unit tests [Delivers #166840979]
1 parent 6fdce5a commit eab0405

23 files changed

+773
-104
lines changed

_test_/App.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ describe('App', () => {
2626
expect(app.find('Switch').length).toBe(1);
2727
});
2828
it('renders a Route component', () => {
29-
expect(app.find('Route').length).toBe(19);
29+
expect(app.find('Route').length).toBe(16);
3030
});
3131
});

_test_/ArticleActions.spec.js

+24-18
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import moxios from 'moxios';
22
import makeMockStore from './Utils/makeMockStore';
3-
import { fetchResponseData, mockData } from './testData/articleData';
3+
import { fetchResponseData, mockData, getArticlesByTagData } from './testData/articleData';
44
import ArticleActions from '../src/actions/ArticleActions';
55
import {
66
SET_LOADING,
77
FETCH_ARTICLES,
88
SET_CURRENT_ARTICLES,
9+
GET_ARTICLES_BY_TAG,
910
} from '../src/actions/types';
1011

11-
const { fetchArticles } = ArticleActions;
12+
const { fetchArticles, getArticlesByTag } = ArticleActions;
1213

1314
const store = makeMockStore({
1415
article: {
16+
totalArticles: 0,
17+
currentArticles: [],
18+
articlesByTag: [],
1519
allArticles: [],
1620
loading: false,
1721
},
@@ -26,23 +30,25 @@ describe('Article Actions', () => {
2630
moxios.uninstall();
2731
});
2832

29-
it('fetches articles', () => {
30-
moxios.wait(() => {
31-
const request = moxios.requests.mostRecent();
32-
request.respondWith({ status: 200, response: fetchResponseData });
33-
});
33+
describe('fetchArticles', () => {
34+
it('fetches articles', () => {
35+
moxios.wait(() => {
36+
const request = moxios.requests.mostRecent();
37+
request.respondWith({ status: 200, response: fetchResponseData });
38+
});
3439

35-
const expectedActions = [
36-
{ type: SET_LOADING },
37-
{ type: FETCH_ARTICLES, payload: mockData },
38-
{ type: SET_CURRENT_ARTICLES, payload: mockData.articles },
39-
];
40+
const expectedActions = [
41+
{ type: SET_LOADING },
42+
{ type: FETCH_ARTICLES, payload: mockData },
43+
{ type: SET_CURRENT_ARTICLES, payload: mockData.articles },
44+
];
4045

41-
return store.dispatch(fetchArticles())
42-
.then(() => {
43-
const actionsCalled = store.getActions();
44-
expect(actionsCalled).toEqual(expectedActions);
45-
expect(actionsCalled[1].type).toEqual(FETCH_ARTICLES);
46-
});
46+
return store.dispatch(fetchArticles())
47+
.then(() => {
48+
const actionsCalled = store.getActions();
49+
expect(actionsCalled).toEqual(expectedActions);
50+
expect(actionsCalled[1].type).toEqual(FETCH_ARTICLES);
51+
});
52+
});
4753
});
4854
});

_test_/ArticleActionsTag.spec.js

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import moxios from 'moxios';
2+
import makeMockStore from './Utils/makeMockStore';
3+
import { getArticlesByTagData } from './testData/articleData';
4+
import ArticleActions from '../src/actions/ArticleActions';
5+
import {
6+
SET_LOADING,
7+
GET_ARTICLES_BY_TAG,
8+
GET_ERRORS,
9+
} from '../src/actions/types';
10+
11+
const { getArticlesByTag } = ArticleActions;
12+
13+
const store = makeMockStore({
14+
article: {
15+
totalArticles: 0,
16+
currentArticles: [],
17+
articlesByTag: [],
18+
allArticles: [],
19+
loading: false,
20+
},
21+
errors: {},
22+
});
23+
24+
describe('Article Actions', () => {
25+
describe('getArticlesByTag', () => {
26+
beforeEach(() => {
27+
moxios.install();
28+
});
29+
afterEach(() => {
30+
moxios.uninstall();
31+
});
32+
33+
it('fetches articles with a specific tag', () => {
34+
moxios.wait(() => {
35+
const request = moxios.requests.mostRecent();
36+
request.respondWith({ status: 200, response: getArticlesByTagData });
37+
});
38+
39+
const expectedActions = [
40+
{ type: SET_LOADING },
41+
{ type: GET_ARTICLES_BY_TAG, payload: getArticlesByTagData.data[0] },
42+
];
43+
44+
return store.dispatch(getArticlesByTag('lagos', 1))
45+
.then(() => {
46+
const actionsCalled = store.getActions();
47+
expect(actionsCalled).toEqual(expectedActions);
48+
});
49+
});
50+
});
51+
52+
53+
describe('getArticlesByTag error', () => {
54+
beforeEach(() => {
55+
moxios.install();
56+
});
57+
afterEach(() => {
58+
moxios.uninstall();
59+
});
60+
61+
it('throws an error', () => {
62+
moxios.wait(() => {
63+
const request = moxios.requests.mostRecent();
64+
const errorResponse = {
65+
status: 400,
66+
message: 'Your search input must be greater than 3 letters',
67+
};
68+
request.respondWith({ status: 200, response: errorResponse });
69+
});
70+
71+
const expectedActions = [
72+
{ type: SET_LOADING },
73+
{ type: GET_ARTICLES_BY_TAG, payload: getArticlesByTagData.data[0] },
74+
{ type: SET_LOADING },
75+
{ type: GET_ERRORS, payload: 'Cannot read property \'0\' of undefined' },
76+
];
77+
78+
return store.dispatch(getArticlesByTag('trjkfjjdhh', 9))
79+
.then(() => {
80+
const actionsCalled = store.getActions();
81+
expect(actionsCalled).toEqual(expectedActions);
82+
});
83+
});
84+
});
85+
});

_test_/FilteredArticles.spec.js

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import React from 'react';
2+
import expect from 'expect';
3+
import Enzyme, { shallow } from 'enzyme';
4+
import Adapter from 'enzyme-adapter-react-16';
5+
6+
import { FilteredArticles } from '../src/views/FilteredArticles';
7+
8+
Enzyme.configure({ adapter: new Adapter() });
9+
10+
describe('Articles', () => {
11+
describe('', () => {
12+
let app;
13+
const props = {
14+
paginate: jest.fn(),
15+
getArticlesByTag: jest.fn(),
16+
loading: false,
17+
articles: {
18+
loading: false,
19+
allArticles: {
20+
articles: [
21+
{
22+
id: 1,
23+
title: 'title 1',
24+
imageUrl: 'http://img.com',
25+
body: 'I am the body',
26+
Category: {
27+
name: 'Game',
28+
},
29+
views: '34',
30+
},
31+
{
32+
id: 2,
33+
title: 'title 2',
34+
imageUrl: 'http://img.com',
35+
body: 'I am the body 2',
36+
Category: {
37+
name: 'Game',
38+
},
39+
views: '34',
40+
},
41+
],
42+
articleCount: 2,
43+
},
44+
},
45+
};
46+
47+
const propsTwo = {
48+
paginate: jest.fn(),
49+
loading: true,
50+
getArticlesByTag: jest.fn(),
51+
articles: {
52+
loading: true,
53+
allArticles: {
54+
articles: [],
55+
articleCount: 2,
56+
},
57+
},
58+
};
59+
60+
beforeEach(() => {
61+
app = shallow(<FilteredArticles {...props} />);
62+
});
63+
64+
it('renders successfully', () => {
65+
expect(app).toBeDefined();
66+
});
67+
68+
it('renders a div component', () => {
69+
expect(app.find('div').length).toBe(2);
70+
});
71+
72+
it('renders a loader component', () => {
73+
const appTwo = shallow(<FilteredArticles {...propsTwo} />);
74+
expect(appTwo.find('Index').length).toBe(1);
75+
});
76+
77+
it('contains a paginate method', () => {
78+
const data = {
79+
selected: 2,
80+
};
81+
const inst = app.instance();
82+
inst.paginate(data);
83+
});
84+
});
85+
});

_test_/FilteredLayout.spec.js

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import React from 'react';
2+
import { shallow } from 'enzyme';
3+
import FilteredLayout from '../src/components/FilteredLayout/index';
4+
5+
describe('Article Layout', () => {
6+
describe('When no article found', () => {
7+
let app;
8+
const article = {
9+
allArticles: [
10+
'No Article Found',
11+
],
12+
};
13+
14+
beforeEach(() => {
15+
app = shallow(<FilteredLayout article={article} />);
16+
});
17+
18+
it('renders successfully', () => {
19+
expect(app).toBeDefined();
20+
});
21+
22+
it('Check for div', () => {
23+
expect(app.find('div').length).toBe(1);
24+
});
25+
});
26+
27+
describe('Load articles', () => {
28+
let app;
29+
const article = {
30+
allArticles: [
31+
{
32+
article: {
33+
id: 3,
34+
title: 'Article 3',
35+
slug: 'article',
36+
description: '',
37+
body: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry',
38+
imageUrl: '',
39+
isDraft: true,
40+
views: 21,
41+
read: 21,
42+
readRatio: 0,
43+
userId: 1,
44+
catId: 1,
45+
Category: {
46+
id: 1,
47+
name: 'Education',
48+
},
49+
User: {
50+
id: 1,
51+
firstName: null,
52+
lastName: null,
53+
userName: 'Alpha',
54+
bio: null,
55+
imageUrl: null,
56+
},
57+
},
58+
},
59+
{
60+
article: {
61+
id: 2,
62+
title: 'Article 2',
63+
slug: 'article',
64+
description: '',
65+
body: 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
66+
imageUrl: '',
67+
isDraft: true,
68+
views: 4,
69+
read: 4,
70+
readRatio: 0,
71+
userId: 1,
72+
catId: 1,
73+
Category: {
74+
id: 1,
75+
name: 'Education',
76+
},
77+
User: {
78+
id: 1,
79+
firstName: null,
80+
lastName: null,
81+
userName: 'Alpha',
82+
bio: null,
83+
imageUrl: null,
84+
},
85+
},
86+
},
87+
],
88+
};
89+
90+
beforeEach(() => {
91+
app = shallow(<FilteredLayout article={article} />);
92+
});
93+
94+
it('renders successfully', () => {
95+
expect(app).toBeDefined();
96+
});
97+
});
98+
});

_test_/LikeIcon.spec.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from 'react';
2+
import { shallow } from 'enzyme';
3+
import LikeIcon from '../src/components/articleLayout/LikeIcon';
4+
5+
describe('LikeIcon', () => {
6+
let app;
7+
8+
beforeEach(() => {
9+
app = shallow(<LikeIcon likeCount={2} />);
10+
});
11+
12+
it('renders successfully', () => {
13+
expect(app).toBeDefined();
14+
});
15+
});

_test_/Tags.spec.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@ describe('Tags', () => {
1818
expect(component).toBeDefined();
1919
});
2020

21-
it('renders three div components', () => {
22-
expect(component.find('div').length).toBe(3);
21+
it('has an onclick handler', () => {
22+
const app = shallow(<Tags tags={['tag']} />);
23+
expect(app.find('Link').length).toBe(1);
24+
app.find('Link').simulate('click');
25+
});
26+
27+
it('renders three Link', () => {
28+
expect(component.find('Link').length).toBe(3);
2329
});
2430

2531
it('renders no div component', () => {

0 commit comments

Comments
 (0)