twreporter-redux
Version:
redux actions and reducers for twreporter website
415 lines (371 loc) • 16 kB
JavaScript
var _chai = require('chai');
var _chai2 = _interopRequireDefault(_chai);
var _chaiAsPromised = require('chai-as-promised');
var _chaiAsPromised2 = _interopRequireDefault(_chaiAsPromised);
var _reduxMockStore = require('redux-mock-store');
var _reduxMockStore2 = _interopRequireDefault(_reduxMockStore);
var _reduxStateFields = require('../../constants/redux-state-fields');
var _reduxStateFields2 = _interopRequireDefault(_reduxStateFields);
var _formApiUrl = require('../../utils/form-api-url');
var _formApiUrl2 = _interopRequireDefault(_formApiUrl);
var _nock = require('nock');
var _nock2 = _interopRequireDefault(_nock);
var _postStyles = require('../../constants/post-styles');
var _postStyles2 = _interopRequireDefault(_postStyles);
var _reduxThunk = require('redux-thunk');
var _reduxThunk2 = _interopRequireDefault(_reduxThunk);
var _actionTypes = require('../../constants/action-types');
var _actionTypes2 = _interopRequireDefault(_actionTypes);
var _posts = require('../posts');
var actions = _interopRequireWildcard(_posts);
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /* global describe, context, it, afterEach */
/*
Testing functions:
fetchAFullPost
fetchListedPosts
fetchEditorPickedPosts
fetchPhotographyPostsOnIndexPage
fetchInfographicPostsOnIndexPage
*/
_chai2.default.use(_chaiAsPromised2.default);
var expect = _chai2.default.expect;
var middlewares = [_reduxThunk2.default];
var mockStore = (0, _reduxMockStore2.default)(middlewares);
var post1 = {
id: 'post-id-1',
slug: 'post-slug-1'
};
var post2 = {
id: 'post-id-2',
slug: 'post-slug-2'
};
var post3 = {
id: 'post-id-3',
slug: 'post-slug-3'
};
var post4 = {
id: 'post-id-4',
slug: 'post-slug-4'
};
process.env.NODE_ENV = 'development';
/* Fetch a full post, whose assets like relateds, leading_video ...etc are all complete,
* @param {string} slug - slug of post
*/
/*
========= Testing fetchAFullPost ==========
*/
describe('Testing fetchAFullPost:', function () {
afterEach(function () {
_nock2.default.cleanAll();
});
context('Post is already existed', function () {
it('Should dispatch no actions and return Promise.resolve()', function () {
var mockSlug = 'mock-slug';
var store = mockStore({
entities: {
posts: {
'mock-slug': {
id: 'mock-id',
slug: 'mock-slug',
brief: {},
full: true
}
}
}
});
store.dispatch(actions.fetchAFullPost(mockSlug));
expect(store.getActions().length).to.equal(0); // no action is dispatched
return expect(store.dispatch(actions.fetchAFullPost(mockSlug))).eventually.equal(undefined);
});
});
context('It loads a full post successfully', function () {
it('Should dispatch types.START_TO_GET_POSTS and types.GET_LISTED_POSTS', function () {
var mockSlug = 'mock-slug';
var store = mockStore({
entities: {
posts: {
'mock-slug': {
id: 'mock-id',
slug: 'mock-slug',
style: 'article',
full: false
}
}
}
});
var mockUrl = (0, _formApiUrl2.default)('posts/' + mockSlug + '?full=true');
var indexOfSlash = mockUrl.indexOf('/', 7);
var mockHost = mockUrl.slice(0, indexOfSlash); // example: 'http://localhost:8080'
var mockPath = mockUrl.slice(indexOfSlash); // example: '/posts?where=.....'
var mockApiResponse = {
record: {
id: 'mock-id',
slug: 'mock-slug',
style: 'article',
full: false
}
};
var expectedRequestAction = {
type: _actionTypes2.default.START_TO_GET_A_FULL_POST,
url: mockUrl
};
var expectedSuccessAction = {
type: _actionTypes2.default.GET_A_FULL_POST,
payload: {
id: 'mock-id',
slug: 'mock-slug',
style: 'article',
full: false
}
};
(0, _nock2.default)(mockHost).get(mockPath).reply(200, mockApiResponse);
return store.dispatch(actions.fetchAFullPost(mockSlug)).then(function () {
expect(store.getActions().length).to.equal(2); // 2 actions: REQUEST && SUCCESS
expect(store.getActions()[0]).to.deep.equal(expectedRequestAction);
expect(store.getActions()[1].type).to.equal(expectedSuccessAction.type);
expect(store.getActions()[1].payload).to.deep.equal(expectedSuccessAction.payload);
});
});
});
context('If the api returns a failure', function () {
it('Should dispatch types.START_TO_GET_POSTS and types.ERROR_TO_GET_POSTS', function () {
var store = mockStore();
var mockSlug = 'mock-slug';
var mockUrl = (0, _formApiUrl2.default)('posts/' + mockSlug + '?full=true');
var indexOfSlash = mockUrl.indexOf('/', 7);
var mockHost = mockUrl.slice(0, indexOfSlash); // example: 'http://localhost:8080'
var mockPath = mockUrl.slice(indexOfSlash); // example: '/posts?where=.....'
var expectedRequestAction = {
type: _actionTypes2.default.START_TO_GET_A_FULL_POST,
url: mockUrl
};
var expectedFailureAction = {
type: _actionTypes2.default.ERROR_TO_GET_A_FULL_POST
};
(0, _nock2.default)(mockHost).get(mockPath).reply(404);
return store.dispatch(actions.fetchAFullPost(mockSlug)).then(function () {
expect(store.getActions().length).to.equal(2); // 2 actions: REQUEST && FAILURE
expect(store.getActions()[0]).to.deep.equal(expectedRequestAction);
expect(store.getActions()[1].type).to.equal(expectedFailureAction.type);
expect(store.getActions()[1].error).to.be.an.instanceof(Error);
});
});
});
});
/* Fetch a listed posts(only containing meta properties),
* such as the posts belonging to the same tag/category/topic.
* @param {string} listID - id of the tag, category or topic
* @param {string} listType - tags, categories or topics
* @param {number} limit - the number of posts you want to get in one request
*/
/*
========= Testing fetchListedPosts ==========
*/
describe('Testing fetchListedPosts:', function () {
afterEach(function () {
_nock2.default.cleanAll();
});
context('There is no more posts to load', function () {
it('Should dispatch no actions and return Promise.resolve()', function () {
var mockArgs = ['mock_target_uuid', // listID
'categories', // type
10];
var store = mockStore({
lists: {
mock_target_uuid: {
total: 4,
items: [post1, post2, post3, post4]
}
}
});
store.dispatch(actions.fetchListedPosts.apply(actions, mockArgs));
expect(store.getActions().length).to.equal(0); // no action is dispatched
return expect(store.dispatch(actions.fetchListedPosts.apply(actions, mockArgs))).eventually.equal(undefined);
});
});
context('It loads posts successfully', function () {
it('Should dispatch types.START_TO_GET_POSTS and types.GET_LISTED_POSTS', function () {
var mockArgs = ['mock_target_uuid', // listID
'categories', // type
1];
var store = mockStore({
// empty lists
lists: {}
});
var mockUrl = (0, _formApiUrl2.default)('posts?where={"categories":{"in":["mock_target_uuid"]}}&limit=1&offset=0');
var indexOfSlash = mockUrl.indexOf('/', 7);
var mockHost = mockUrl.slice(0, indexOfSlash); // example: 'http://localhost:8080'
var mockPath = mockUrl.slice(indexOfSlash); // example: '/posts?where=.....'
var mockApiResponse = {
records: [{
_id: 'mock_category_article_id_01',
title: 'mock_category_article_title',
slug: 'mock-category-article-slug',
style: 'article',
og_description: 'mock_category_article_title_og_description'
}],
meta: {
limit: 1,
total: 2,
offset: 0
}
};
var expectedRequestAction = {
type: _actionTypes2.default.START_TO_GET_POSTS,
url: mockUrl
};
var expectedSuccessAction = {
type: _actionTypes2.default.GET_LISTED_POSTS,
payload: {
items: [{
_id: 'mock_category_article_id_01',
title: 'mock_category_article_title',
slug: 'mock-category-article-slug',
style: 'article',
og_description: 'mock_category_article_title_og_description'
}],
total: 2,
listID: 'mock_target_uuid'
}
};
(0, _nock2.default)(mockHost).get(mockPath).reply(200, mockApiResponse);
return store.dispatch(actions.fetchListedPosts.apply(actions, mockArgs)).then(function () {
expect(store.getActions().length).to.equal(2); // 2 actions: REQUEST && SUCCESS
expect(store.getActions()[0]).to.deep.equal(expectedRequestAction);
expect(store.getActions()[1].type).to.equal(expectedSuccessAction.type);
expect(store.getActions()[1].payload).to.deep.equal(expectedSuccessAction.payload);
});
});
});
context('If the api returns a failure', function () {
it('Should dispatch types.START_TO_GET_POSTS and types.ERROR_TO_GET_POSTS', function () {
var mockArgs = ['mock_target_uuid', // listID
'categories', // type
1];
var store = mockStore({
// empty lists
lists: {}
});
var mockUrl = (0, _formApiUrl2.default)('posts?where={"categories":{"in":["mock_target_uuid"]}}&limit=1&offset=0');
var indexOfSlash = mockUrl.indexOf('/', 7);
var mockHost = mockUrl.slice(0, indexOfSlash); // example: 'http://localhost:3030'
var mockPath = mockUrl.slice(indexOfSlash); // example: '/mata?where=.....'
var expectedRequestAction = {
type: _actionTypes2.default.START_TO_GET_POSTS,
url: mockUrl
};
var expectedFailedAction = {
type: _actionTypes2.default.ERROR_TO_GET_LISTED_POSTS
};
(0, _nock2.default)(mockHost).get(mockPath).reply(404, {});
return store.dispatch(actions.fetchListedPosts.apply(actions, mockArgs)).then(function () {
expect(store.getActions().length).to.equal(2); // 2 actions: REQUEST && SUCCESS
expect(store.getActions()[0]).to.deep.equal(expectedRequestAction);
expect(store.getActions()[1].type).to.equal(expectedFailedAction.type);
expect(store.getActions()[1].error).to.be.an.instanceof(Error);
});
});
});
});
/** Fetch those posts picked by editors
*/
/*
========= Testing fetchEditorPickedPosts ==========
*/
describe('Testing fetchEditorPickedPosts:', function () {
after(function () {
_nock2.default.cleanAll();
});
context('Posts picked by editor are already existed', function () {
it('Should do nothing', function () {
var store = mockStore(_defineProperty({}, _reduxStateFields2.default.indexPage, _defineProperty({}, _reduxStateFields2.default.editorPicks, [post1, post2, post3, post4])));
store.dispatch(actions.fetchEditorPickedPosts());
expect(store.getActions().length).to.equal(0); // no action is dispatched
return expect(store.dispatch(actions.fetchEditorPickedPosts())).eventually.equal(undefined);
});
});
context('Load posts picked by editor', function () {
it('Should dispatch types.GET_EDITOR_PICKED_POSTS', function () {
var store = mockStore({});
(0, _nock2.default)('http://localhost:8080').get(encodeURI('/v1/posts?where={"is_featured":true}&limit=6')).reply(200, {
records: [{ slug: 'slug-1' }, { slug: 'slug-2' }, { slug: 'slug-3' }, { slug: 'slug-4' }, { slug: 'slug-5' }, { slug: 'slug-6' }]
});
return store.dispatch(actions.fetchEditorPickedPosts()).then(function () {
expect(store.getActions().length).to.equal(2); // START and GET
expect(store.getActions()[1].type).to.equal(_actionTypes2.default.GET_EDITOR_PICKED_POSTS);
expect(store.getActions()[1].payload.items.length).to.equal(6);
});
});
});
});
/**
* fetchPhotographyPostsOnIndexPage
* This function will fetch 10 latest posts with photography style,
* It's specifically made for index page
*/
/*
========= Testing fetchPhotographyPostsOnIndexPage ==========
*/
describe('Testing fetchPhotographyPostsOnIndexPage:', function () {
after(function () {
_nock2.default.cleanAll();
});
context('Posts are already existed', function () {
it('Should do nothing', function () {
var store = mockStore(_defineProperty({}, _reduxStateFields2.default.indexPage, _defineProperty({}, _reduxStateFields2.default.photos, [post1, post2, post3, post4])));
store.dispatch(actions.fetchPhotographyPostsOnIndexPage());
expect(store.getActions().length).to.equal(0); // no action is dispatched
return expect(store.dispatch(actions.fetchPhotographyPostsOnIndexPage())).eventually.equal(undefined);
});
});
context('Load posts if needed', function () {
it('Should dispatch types.GET_PHOTOGRAPHY_POSTS_FOR_INDEX_PAGE', function () {
var store = mockStore({});
(0, _nock2.default)('http://localhost:8080').get(encodeURI('/v1/posts?where={"style":"' + _postStyles2.default.photography + '"}&limit=10')).reply(200, {
records: [{ slug: 'slug-1' }, { slug: 'slug-2' }, { slug: 'slug-3' }]
});
return store.dispatch(actions.fetchPhotographyPostsOnIndexPage()).then(function () {
expect(store.getActions().length).to.equal(2); // START and GET
expect(store.getActions()[1].type).to.equal(_actionTypes2.default.GET_PHOTOGRAPHY_POSTS_FOR_INDEX_PAGE);
expect(store.getActions()[1].payload.items.length).to.equal(3);
});
});
});
});
/**
* fetchInfographicPostsOnIndexPage
* This function will fetch 10 latest posts with interactive style,
* It's specifically made for index page
*/
/*
========= Testing fetchInfographicPostsOnIndexPage ==========
*/
describe('Testing fetchInfographicPostsOnIndexPage:', function () {
after(function () {
_nock2.default.cleanAll();
});
context('Posts are already existed', function () {
it('Should do nothing', function () {
var store = mockStore(_defineProperty({}, _reduxStateFields2.default.indexPage, _defineProperty({}, _reduxStateFields2.default.infographics, [post1, post2, post3, post4])));
store.dispatch(actions.fetchInfographicPostsOnIndexPage());
expect(store.getActions().length).to.equal(0); // no action is dispatched
return expect(store.dispatch(actions.fetchInfographicPostsOnIndexPage())).eventually.equal(undefined);
});
});
context('Load posts if needed', function () {
it('Should dispatch types.GET_INFOGRAPHIC_POSTS_FOR_INDEX_PAGE)', function () {
var store = mockStore({});
(0, _nock2.default)('http://localhost:8080').get(encodeURI('/v1/posts?where={"style":"' + _postStyles2.default.infographic + '"}&limit=10')).reply(200, {
records: [{ slug: 'slug-1' }, { slug: 'slug-2' }]
});
return store.dispatch(actions.fetchInfographicPostsOnIndexPage()).then(function () {
expect(store.getActions().length).to.equal(2); // START and GET
expect(store.getActions()[1].type).to.equal(_actionTypes2.default.GET_INFOGRAPHIC_POSTS_FOR_INDEX_PAGE);
expect(store.getActions()[1].payload.items.length).to.equal(2);
});
});
});
});
;