UNPKG

twreporter-redux

Version:

redux actions and reducers for twreporter website

415 lines (371 loc) 16 kB
'use strict'; 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); }); }); }); });