diff --git a/.travis.yml b/.travis.yml index 1c75977..75bb68a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,10 @@ sudo: required language: node_js node_js: - - "4.1" - - "5.3" - "6.0" branches: only: - - master + - phase-1 env: global: - CXX=g++-4.8 @@ -19,13 +17,15 @@ addons: - ubuntu-toolchain-r-test packages: - g++-4.8 -before_script: +before_install: - npm cache clean - - npm install -g grunt-cli - if [ "$GIT_VERSION" = "edge" ]; then sudo add-apt-repository ppa:git-core/ppa -y && sudo apt-get update -q && sudo apt-get install -y git; fi - git config --global user.email "test@testy.com" - git config --global user.name "Test testy" - git version - - grunt -d -after_script: - - grunt travisnpmpublish +install: + - npm install + +script: + - node -v + - npm run test-react \ No newline at end of file diff --git a/config/localStorageMock.js b/config/localStorageMock.js new file mode 100644 index 0000000..8b0b8d4 --- /dev/null +++ b/config/localStorageMock.js @@ -0,0 +1,23 @@ +class LocalStorageMock { + constructor() { + this.store = {}; + } + + clear() { + this.store = {}; + } + + getItem(key) { + return this.store[key]; + } + + setItem(key, value) { + this.store[key] = value.toString(); + } + + removeItem(key) { + delete this.store[key]; + } +}; + +global.localStorage = new LocalStorageMock; diff --git a/package.json b/package.json index 8dc29e6..8c2a9b8 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "react-dom": "^15.5.4", "react-redux": "^5.0.4", "redux": "^3.6.0", - "redux-thunk": "^2.2.0", + "redux-api-middleware": "^1.0.3", "rimraf": "~2.6.1", "semver": "~5.3.0", "serve-static": "~1.12.2", @@ -125,13 +125,16 @@ "jest": "18.1.0", "json-loader": "0.5.4", "mocha": "~3.3.0", + "nock": "^9.0.13", "node-sass": "^4.5.3", "object-assign": "4.1.1", "phantomjs-prebuilt": "~2.1.14", "postcss-loader": "1.2.2", "promise": "7.1.1", "react-dev-utils": "^0.5.2", + "redux-mock-store": "^1.2.3", "sass-loader": "^6.0.5", + "sinon": "^2.3.4", "style-loader": "0.13.1", "supertest": "~3.0.0", "url-loader": "0.5.7", @@ -145,10 +148,11 @@ "src/**/*.{js,jsx}" ], "setupFiles": [ - "/config/polyfills.js" + "/config/polyfills.js", + "/config/localStorageMock.js" ], "testPathIgnorePatterns": [ - "[/\\\\](build|docs|node_modules|scripts)[/\\\\]" + "[/\\\\](build|docs|node_modules|scripts|clicktests)[/\\\\]" ], "testEnvironment": "node", "testURL": "http://localhost", @@ -162,7 +166,10 @@ ], "moduleNameMapper": { "^react-native$": "react-native-web" - } + }, + "modulePaths": [ + "src-react" + ] }, "babel": { "presets": [ diff --git a/scripts/test.js b/scripts/test.js index 1995442..e7c5843 100644 --- a/scripts/test.js +++ b/scripts/test.js @@ -1,4 +1,9 @@ 'use strict'; +const regeneratorRuntime = require('babel-runtime/regenerator'); + +if (!regeneratorRuntime.default) { + regeneratorRuntime.default = regeneratorRuntime; +} process.env.NODE_ENV = 'test'; process.env.PUBLIC_URL = ''; diff --git a/src-react/__tests__/actions/ungit-config.test.js b/src-react/__tests__/actions/ungit-config.test.js new file mode 100644 index 0000000..db24256 --- /dev/null +++ b/src-react/__tests__/actions/ungit-config.test.js @@ -0,0 +1,22 @@ +import { CALL_API } from 'redux-api-middleware'; +import expect from 'expect.js'; + +import * as types from 'constants/action-types'; +import { fetchUngitConfig } from 'actions/ungit-config'; + +describe('ungit-config.js action', () => { + describe('fetchUngitConfig', () => { + it('returns CALL_API action object', function(){ + const action = fetchUngitConfig(); + + expect(action[CALL_API]).to.be.an('object'); + expect(action[CALL_API].endpoint).to.eql('http://localhost:8448/ungit/config'); + expect(action[CALL_API].method).to.eql('GET'); + expect(action[CALL_API].types).to.be.an('array'); + expect(action[CALL_API].types[0]).to.eql(types.FETCH_UNGIT_CONFIG_REQUEST); + expect(action[CALL_API].types[1]).to.be.an('object'); + expect(action[CALL_API].types[1].type).to.eql(types.FETCH_UNGIT_CONFIG_SUCCESS); + expect(action[CALL_API].types[2]).to.eql(types.FETCH_UNGIT_CONFIG_FAILURE); + }); + }); +}); \ No newline at end of file diff --git a/src-react/__tests__/actions/user-config.test.js b/src-react/__tests__/actions/user-config.test.js new file mode 100644 index 0000000..60d25bb --- /dev/null +++ b/src-react/__tests__/actions/user-config.test.js @@ -0,0 +1,21 @@ +import { CALL_API } from 'redux-api-middleware'; +import expect from 'expect.js'; + +import * as types from 'constants/action-types'; +import { fetchUserConfig } from 'actions/user-config'; + +describe('user-config.js action', () => { + describe('fetchUserConfig', () => { + it('returns CALL_API action object', function(){ + const action = fetchUserConfig(); + + expect(action[CALL_API]).to.be.an('object'); + expect(action[CALL_API].endpoint).to.eql('http://localhost:8448/api/userconfig'); + expect(action[CALL_API].method).to.eql('GET'); + expect(action[CALL_API].types).to.be.an('array'); + expect(action[CALL_API].types[0]).to.eql(types.FETCH_USER_CONFIG_REQUEST); + expect(action[CALL_API].types[1]).to.eql(types.FETCH_USER_CONFIG_SUCCESS); + expect(action[CALL_API].types[2]).to.eql(types.FETCH_USER_CONFIG_FAILURE); + }); + }); +}); \ No newline at end of file diff --git a/src-react/__tests__/actions/version.test.js b/src-react/__tests__/actions/version.test.js new file mode 100644 index 0000000..a9ac579 --- /dev/null +++ b/src-react/__tests__/actions/version.test.js @@ -0,0 +1,35 @@ +import { CALL_API } from 'redux-api-middleware'; +import expect from 'expect.js'; + +import * as types from 'constants/action-types'; +import { fetchLatestVersion, fetchGitVersion } from 'actions/version'; + +describe('version.js action', () => { + describe('fetchLatestVersion', () => { + it('returns CALL_API action object', function(){ + const action = fetchLatestVersion(); + + expect(action[CALL_API]).to.be.an('object'); + expect(action[CALL_API].endpoint).to.eql('http://localhost:8448/api/latestversion'); + expect(action[CALL_API].method).to.eql('GET'); + expect(action[CALL_API].types).to.be.an('array'); + expect(action[CALL_API].types[0]).to.eql(types.FETCH_LATEST_VERSION_REQUEST); + expect(action[CALL_API].types[1]).to.eql(types.FETCH_LATEST_VERSION_SUCCESS); + expect(action[CALL_API].types[2]).to.eql(types.FETCH_LATEST_VERSION_FAILURE); + }); + }); + + describe('fetchGitVersion', () => { + it('returns CALL_API action object', function(){ + const action = fetchGitVersion(); + + expect(action[CALL_API]).to.be.an('object'); + expect(action[CALL_API].endpoint).to.eql('http://localhost:8448/api/gitversion'); + expect(action[CALL_API].method).to.eql('GET'); + expect(action[CALL_API].types).to.be.an('array'); + expect(action[CALL_API].types[0]).to.eql(types.FETCH_GIT_VERSION_REQUEST); + expect(action[CALL_API].types[1]).to.eql(types.FETCH_GIT_VERSION_SUCCESS); + expect(action[CALL_API].types[2]).to.eql(types.FETCH_GIT_VERSION_FAILURE); + }); + }); +}); \ No newline at end of file diff --git a/src-react/__tests__/middlewares/redux-api/ungit-config.test.js b/src-react/__tests__/middlewares/redux-api/ungit-config.test.js new file mode 100644 index 0000000..50aedbc --- /dev/null +++ b/src-react/__tests__/middlewares/redux-api/ungit-config.test.js @@ -0,0 +1,79 @@ +import nock from 'nock'; +import sinon from 'sinon'; +import expect from 'expect.js'; +import configureStore from 'redux-mock-store'; +import { createStore, applyMiddleware } from 'redux'; +import { apiMiddleware, CALL_API } from 'redux-api-middleware'; + +import * as types from 'constants/action-types'; +import { fetchUngitConfig } from 'actions/ungit-config'; + +const createMockStore = configureStore([ apiMiddleware ]); + +describe('redux-api-middleware::ungit-config', () => { + describe('fetchUngitConfig successfully', () => { + const mockPayload = { message: 'success' }; + + beforeEach(() => { + nock('http://localhost:8448') + .get('/ungit/config') + .reply(200, mockPayload); + + nock('http://localhost:8448') + .get('/api/userconfig') + .reply(200, mockPayload); + }); + + it('should dispatch \'FETCH_UNGIT_CONFIG_REQUEST\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 1) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_UNGIT_CONFIG_REQUEST); + done(); + } + }); + store.dispatch(fetchUngitConfig()); + }); + + it('should dispatch \'FETCH_UNGIT_CONFIG_SUCCESS\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 2) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_UNGIT_CONFIG_REQUEST); + expect(dispatchedActions[1].type).to.eql(types.FETCH_UNGIT_CONFIG_SUCCESS); + expect(dispatchedActions[1].payload).to.eql(mockPayload); + done(); + } + }); + store.dispatch(fetchUngitConfig()); + }); + }); + + describe('fetchUngitConfig fails', () => { + + beforeEach(() => { + nock('http://localhost:8448') + .get('/ungit/config') + .reply(500, null); + }); + + it('should dispatch \'FETCH_UNGIT_CONFIG_FAILURE\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 2) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_UNGIT_CONFIG_REQUEST); + expect(dispatchedActions[1].type).to.eql(types.FETCH_UNGIT_CONFIG_FAILURE); + expect(dispatchedActions[1].payload).to.be.an('object'); + done(); + } + }); + store.dispatch(fetchUngitConfig()); + }); + }); +}); \ No newline at end of file diff --git a/src-react/__tests__/middlewares/redux-api/user-config.test.js b/src-react/__tests__/middlewares/redux-api/user-config.test.js new file mode 100644 index 0000000..a284dab --- /dev/null +++ b/src-react/__tests__/middlewares/redux-api/user-config.test.js @@ -0,0 +1,75 @@ +import nock from 'nock'; +import sinon from 'sinon'; +import expect from 'expect.js'; +import configureStore from 'redux-mock-store'; +import { createStore, applyMiddleware } from 'redux'; +import { apiMiddleware, CALL_API } from 'redux-api-middleware'; + +import * as types from 'constants/action-types'; +import { fetchUserConfig } from 'actions/user-config'; + +const createMockStore = configureStore([ apiMiddleware ]); + +describe('redux-api-middleware::user-config', () => { + describe('fetchUserConfig successfully', () => { + const mockPayload = { message: 'success' }; + + beforeEach(() => { + nock('http://localhost:8448') + .get('/api/userconfig') + .reply(200, mockPayload); + }); + + it('should dispatch \'FETCH_USER_CONFIG_REQUEST\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 1) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_USER_CONFIG_REQUEST); + done(); + } + }); + store.dispatch(fetchUserConfig()); + }); + + it('should dispatch \'FETCH_USER_CONFIG_SUCCESS\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 2) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_USER_CONFIG_REQUEST); + expect(dispatchedActions[1].type).to.eql(types.FETCH_USER_CONFIG_SUCCESS); + expect(dispatchedActions[1].payload).to.eql(mockPayload); + done(); + } + }); + store.dispatch(fetchUserConfig()); + }); + }); + + describe('fetchUserConfig fails', () => { + + beforeEach(() => { + nock('http://localhost:8448') + .get('/api/userconfig') + .reply(500, null); + }); + + it('should dispatch \'FETCH_USER_CONFIG_FAILURE\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 2) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_USER_CONFIG_REQUEST); + expect(dispatchedActions[1].type).to.eql(types.FETCH_USER_CONFIG_FAILURE); + expect(dispatchedActions[1].payload).to.be.an('object'); + done(); + } + }); + store.dispatch(fetchUserConfig()); + }); + }); +}); \ No newline at end of file diff --git a/src-react/__tests__/middlewares/redux-api/version.test.js b/src-react/__tests__/middlewares/redux-api/version.test.js new file mode 100644 index 0000000..fa795b2 --- /dev/null +++ b/src-react/__tests__/middlewares/redux-api/version.test.js @@ -0,0 +1,137 @@ +import nock from 'nock'; +import sinon from 'sinon'; +import expect from 'expect.js'; +import configureStore from 'redux-mock-store'; +import { createStore, applyMiddleware } from 'redux'; +import { apiMiddleware, CALL_API } from 'redux-api-middleware'; + +import * as types from 'constants/action-types'; +import { fetchLatestVersion, fetchGitVersion } from 'actions/version'; + +const createMockStore = configureStore([ apiMiddleware ]); + +describe('redux-api-middleware::version', () => { + describe('fetchLatestVersion successfully', () => { + const mockPayload = { message: 'success' }; + + beforeEach(() => { + nock('http://localhost:8448') + .get('/api/latestversion') + .reply(200, mockPayload); + }); + + it('should dispatch \'FETCH_LATEST_VERSION_REQUEST\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 1) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_LATEST_VERSION_REQUEST); + done(); + } + }); + store.dispatch(fetchLatestVersion()); + }); + + it('should dispatch \'FETCH_USER_CONFIG_SUCCESS\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 2) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_LATEST_VERSION_REQUEST); + expect(dispatchedActions[1].type).to.eql(types.FETCH_LATEST_VERSION_SUCCESS); + expect(dispatchedActions[1].payload).to.eql(mockPayload); + done(); + } + }); + store.dispatch(fetchLatestVersion()); + }); + }); + + describe('fetchLatestVersion fails', () => { + + beforeEach(() => { + nock('http://localhost:8448') + .get('/api/latestversion') + .reply(500, null); + }); + + it('should dispatch \'FETCH_LATEST_VERSION_FAILURE\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 2) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_LATEST_VERSION_REQUEST); + expect(dispatchedActions[1].type).to.eql(types.FETCH_LATEST_VERSION_FAILURE); + expect(dispatchedActions[1].payload).to.be.an('object'); + done(); + } + }); + store.dispatch(fetchLatestVersion()); + }); + }); + + describe('fetchGitVersion successfully', () => { + const mockPayload = { message: 'success' }; + + beforeEach(() => { + nock('http://localhost:8448') + .get('/api/gitversion') + .reply(200, mockPayload); + }); + + it('should dispatch \'FETCH_GIT_VERSION_REQUEST\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 1) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_GIT_VERSION_REQUEST); + done(); + } + }); + store.dispatch(fetchGitVersion()); + }); + + it('should dispatch \'FETCH_GIT_VERSION_SUCCESS\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 2) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_GIT_VERSION_REQUEST); + expect(dispatchedActions[1].type).to.eql(types.FETCH_GIT_VERSION_SUCCESS); + expect(dispatchedActions[1].payload).to.eql(mockPayload); + done(); + } + }); + store.dispatch(fetchGitVersion()); + }); + }); + + describe('fetchGitVersion fails', () => { + + beforeEach(() => { + nock('http://localhost:8448') + .get('/api/gitversion') + .reply(500, null); + }); + + it('should dispatch \'FETCH_GIT_VERSION_FAILURE\'', done => { + const store = createMockStore({}); + + store.subscribe(() => { + const dispatchedActions = store.getActions(); + if (dispatchedActions.length === 2) { + expect(dispatchedActions[0].type).to.eql(types.FETCH_GIT_VERSION_REQUEST); + expect(dispatchedActions[1].type).to.eql(types.FETCH_GIT_VERSION_FAILURE); + expect(dispatchedActions[1].payload).to.be.an('object'); + done(); + } + }); + store.dispatch(fetchGitVersion()); + }); + }); +}); \ No newline at end of file diff --git a/src-react/__tests__/reducers/app.js b/src-react/__tests__/reducers/app.js new file mode 100644 index 0000000..6423dfb --- /dev/null +++ b/src-react/__tests__/reducers/app.js @@ -0,0 +1,231 @@ +import sinon from 'sinon'; +import * as types from 'constants/action-types'; + +import app from 'reducers/app'; + +describe('app.js reducers', () => { + let initialState; + + beforeEach(() => { + initialState = { + gitVersionErrorVisible: false, + showNewVersionAvailable: false, + showBugtrackingNagscreen: false, + showNPSSurvey: false + }; + }); + + describe('when action doesn\'t match any case' , () => { + + it('should return original state except the showNPSSurvey state', () => { + const state = app(initialState, { type: types.NO_OP }); + expect(state.gitVersionErrorVisible).toEqual(initialState.gitVersionErrorVisible); + expect(state.showNewVersionAvailable).toEqual(initialState.showNewVersionAvailable); + expect(state.showBugtrackingNagscreen).toEqual(initialState.showBugtrackingNagscreen); + }); + + describe('but last NPS dismissed >= 6 month and Math.random < 0.01', () => { + beforeEach(() => { + localStorage.setItem('NPSSurveyLastDismissed', 1466227885); + sinon.stub(Math, 'random').returns(0.006); + }); + + it('showNPSSurvey state will be true', () => { + const state = app(initialState, { type: types.NO_OP }); + expect(state.showNPSSurvey).toEqual(true); + }); + + afterEach(() => { + Math.random.restore(); + }); + }); + + describe('but last NPS dismissed < 6 month', () => { + beforeEach(() => { + localStorage.setItem('NPSSurveyLastDismissed', Date.now()); + sinon.stub(Math, 'random').returns(0.1); + }); + + it('showNPSSurvey state will be false', () => { + const state = app(initialState, { type: types.NO_OP }); + expect(state.showNPSSurvey).toEqual(false); + }); + + afterEach(() => { + Math.random.restore(); + }); + }); + + describe('but Math.random >= 0.01', () => { + beforeEach(() => { + localStorage.setItem('NPSSurveyLastDismissed', 1466227885); + sinon.stub(Math, 'random').returns(0.1); + }); + + it('showNPSSurvey state will be false', () => { + const state = app(initialState, { type: types.NO_OP }); + expect(state.showNPSSurvey).toEqual(false); + }); + + afterEach(() => { + Math.random.restore(); + }); + }); + }); + + describe('when FETCH_UNGIT_CONFIG_SUCCESS action dispatch', () => { + describe('if ungitConfig.config.bugtracking is false and bugtrackingNagscreenDismissed is false', () => { + it('showBugtrackingNagscreen state will be true', () => { + const ungitConfig = { config: { bugtracking: false } }; + const state = app(initialState, { type: types.FETCH_UNGIT_CONFIG_SUCCESS, payload: ungitConfig }, { ungitConfig }); + expect(state.showBugtrackingNagscreen).toEqual(true); + }); + }); + + describe('if ungitConfig.config.bugtracking is true', () => { + it('showBugtrackingNagscreen state will be false', () => { + const ungitConfig = { config: { bugtracking: true } }; + const state = app(initialState, { type: types.FETCH_UNGIT_CONFIG_SUCCESS, payload: ungitConfig }, { ungitConfig }); + expect(state.showBugtrackingNagscreen).toEqual(false); + }); + }); + + describe('if bugtrackingNagscreenDismissed is true', () => { + it('showBugtrackingNagscreen state will be false', () => { + localStorage.setItem('bugtrackingNagscreenDismissed', true); + const ungitConfig = { config: { bugtracking: false } }; + const state = app(initialState, { type: types.FETCH_UNGIT_CONFIG_SUCCESS, payload: ungitConfig }, { ungitConfig }); + expect(state.showBugtrackingNagscreen).toEqual(false); + }); + }); + }); + + describe('when FETCH_GIT_VERSION_SUCCESS action dispatch', () => { + describe('if ungitConfig.config.gitVersionCheckOverride is false and gitVersionError is defined && gitVersionErrorDismissed is false', () => { + it('gitVersionErrorVisible state will be true', () => { + localStorage.setItem('gitVersionErrorDismissed', false); + const ungitConfig = { config: { gitVersionCheckOverride: false } }; + const gitVersion = { + satisfied: false, + error: 'Failed to parse git version number.' + }; + const config = { ungitConfig, versions: { gitVersion } }; + + const state = app(initialState, { type: types.FETCH_GIT_VERSION_SUCCESS, payload: gitVersion }, config); + expect(state.gitVersionErrorVisible).toEqual(true); + }); + }); + + describe('if ungitConfig.config.gitVersionCheckOverride is true', () => { + it('gitVersionErrorVisible state will be false', () => { + localStorage.setItem('gitVersionErrorDismissed', false); + const ungitConfig = { config: { gitVersionCheckOverride: true } }; + const gitVersion = { + satisfied: false, + error: 'Failed to parse git version number.' + }; + const config = { ungitConfig, versions: { gitVersion } }; + + const state = app(initialState, { type: types.FETCH_GIT_VERSION_SUCCESS, payload: gitVersion }, config); + expect(state.gitVersionErrorVisible).toEqual(false); + }); + }); + + describe('if gitVersionError is not defined', () => { + it('gitVersionErrorVisible state will be false', () => { + localStorage.setItem('gitVersionErrorDismissed', false); + const ungitConfig = { config: { gitVersionCheckOverride: false } }; + const gitVersion = { satisfied: true }; + const config = { ungitConfig, versions: { gitVersion } }; + + const state = app(initialState, { type: types.FETCH_GIT_VERSION_SUCCESS, payload: gitVersion }, config); + expect(state.gitVersionErrorVisible).toEqual(false); + }); + }); + + describe('if gitVersionErrorDismissed is true', () => { + it('gitVersionErrorVisible state will be false', () => { + localStorage.setItem('gitVersionErrorDismissed', true); + const ungitConfig = { config: { gitVersionCheckOverride: false } }; + const gitVersion = { + satisfied: false, + error: 'Failed to parse git version number.' + }; + const config = { ungitConfig, versions: { gitVersion } }; + + const state = app(initialState, { type: types.FETCH_GIT_VERSION_SUCCESS, payload: gitVersion }, config); + expect(state.gitVersionErrorVisible).toEqual(false); + }); + }); + }); + + describe('when FETCH_LATEST_VERSION_SUCCESS action dispatch', () => { + describe('gitVersionCheckOverride is false and latestVersion.outdated is true', () => { + it('showNewVersionAvailable state will be true', () => { + const ungitConfig = { config: { gitVersionCheckOverride: false } }; + const latestVersion = { outdated: true }; + const config = { ungitConfig, versions: { latestVersion } }; + + const state = app(initialState, { type: types.FETCH_LATEST_VERSION_SUCCESS, payload: latestVersion }, config); + expect(state.showNewVersionAvailable).toEqual(true); + }); + }); + + describe('gitVersionCheckOverride is true', () => { + it('showNewVersionAvailable state will be false', () => { + const ungitConfig = { config: { gitVersionCheckOverride: true } }; + const latestVersion = { outdated: true }; + const config = { ungitConfig, versions: { latestVersion } }; + + const state = app(initialState, { type: types.FETCH_LATEST_VERSION_SUCCESS, payload: latestVersion }, config); + expect(state.showNewVersionAvailable).toEqual(false); + }); + }); + + describe('latestVersion.outdated is true', () => { + it('showNewVersionAvailable state will be false', () => { + const ungitConfig = { config: { gitVersionCheckOverride: false } }; + const latestVersion = { outdated: false }; + const config = { ungitConfig, versions: { latestVersion } }; + + const state = app(initialState, { type: types.FETCH_LATEST_VERSION_SUCCESS, payload: latestVersion }, config); + expect(state.showNewVersionAvailable).toEqual(false); + }); + }); + }); + + describe('when FETCH_USER_CONFIG_SUCCESS action dispatch', () => { + describe('userConfig.bugtracking = false and bugtrackingNagscreenDismissed = false', () => { + it('showBugtrackingNagscreen state will be true', () => { + const userConfig = { bugtracking: false }; + const ungitConfig = { config: { bugtracking: true } }; + localStorage.setItem('bugtrackingNagscreenDismissed', false); + + const state = app(initialState, { type: types.FETCH_USER_CONFIG_SUCCESS, payload: userConfig }, { userConfig, ungitConfig }); + expect(state.showBugtrackingNagscreen).toEqual(true); + }); + }); + + describe('userConfig.bugtracking = true', () => { + it('showBugtrackingNagscreen state will be false', () => { + const userConfig = { bugtracking: true }; + const ungitConfig = { config: { bugtracking: true } }; + localStorage.setItem('bugtrackingNagscreenDismissed', false); + + const state = app(initialState, { type: types.FETCH_USER_CONFIG_SUCCESS, payload: userConfig }, { userConfig, ungitConfig }); + expect(state.showBugtrackingNagscreen).toEqual(false); + }); + }); + + describe('bugtrackingNagscreenDismissed = true', () => { + it('showBugtrackingNagscreen state will be false', () => { + const userConfig = { bugtracking: false }; + const ungitConfig = { config: { bugtracking: true } }; + localStorage.setItem('bugtrackingNagscreenDismissed', true); + + const state = app(initialState, { type: types.FETCH_USER_CONFIG_SUCCESS, payload: userConfig }, { userConfig, ungitConfig }); + expect(state.showBugtrackingNagscreen).toEqual(false); + }); + }); + }); +}); \ No newline at end of file diff --git a/src-react/__tests__/reducers/path.test.js b/src-react/__tests__/reducers/path.test.js new file mode 100644 index 0000000..892857d --- /dev/null +++ b/src-react/__tests__/reducers/path.test.js @@ -0,0 +1,93 @@ +import * as types from 'constants/action-types'; + +import path from 'reducers/path'; + +describe('path.js reducers', () => { + let initialState; + + const REQUEST_ACTIONS = [ + types.FETCH_USER_CONFIG_REQUEST, + types.FETCH_LATEST_VERSION_REQUEST, + types.FETCH_GIT_VERSION_REQUEST, + types.FETCH_UNGIT_CONFIG_REQUEST + ]; + + const SUCCESS_ACTIONS = [ + types.FETCH_USER_CONFIG_SUCCESS, + types.FETCH_LATEST_VERSION_SUCCESS, + types.FETCH_GIT_VERSION_SUCCESS, + types.FETCH_UNGIT_CONFIG_SUCCESS + ]; + + const FAILURE_ACTIONS = [ + types.FETCH_USER_CONFIG_FAILURE, + types.FETCH_LATEST_VERSION_FAILURE, + types.FETCH_GIT_VERSION_FAILURE, + types.FETCH_UNGIT_CONFIG_FAILURE + ]; + + beforeEach(() => { + initialState = { + pending: null, + errMessage: [] + }; + }); + + it('should return original state if action doesn\'t match any case' , function() { + const state = path(initialState, { type: types.NO_OP }); + expect(state.pending).toEqual(initialState.pending); + expect(state.errMessage.length).toEqual(initialState.errMessage.length); + }); + + REQUEST_ACTIONS.forEach(actionName => { + describe(`when ${actionName} action dispatch`, () => { + beforeEach(() => { + initialState = { + pending: 1, + errMessage: [] + }; + }); + it('pending state should be plus one', () => { + const action = { type: actionName }; + + const state = path(initialState, action); + expect(state.pending).toEqual(initialState.pending + 1); + }); + }); + }); + + SUCCESS_ACTIONS.forEach(actionName => { + describe(`when ${actionName} action dispatch`, () => { + beforeEach(() => { + initialState = { + pending: 1, + errMessage: [] + }; + }); + it('pending state should be minused one', () => { + const action = { type: actionName }; + + const state = path(initialState, action); + expect(state.pending).toEqual(initialState.pending - 1); + }); + }); + }); + + FAILURE_ACTIONS.forEach(actionName => { + describe(`when ${actionName} action dispatch`, () => { + beforeEach(() => { + initialState = { + pending: 1, + errMessage: [] + }; + }); + it('pending state should be minused one', () => { + const action = { type: actionName, payload: { message: 'error' } }; + + const state = path(initialState, action); + expect(state.pending).toEqual(initialState.pending - 1); + expect(state.errMessage[0]).toEqual(action.payload.message); + }); + }); + }); +}); \ No newline at end of file diff --git a/src-react/__tests__/reducers/ungit-config.test.js b/src-react/__tests__/reducers/ungit-config.test.js new file mode 100644 index 0000000..f9486c6 --- /dev/null +++ b/src-react/__tests__/reducers/ungit-config.test.js @@ -0,0 +1,32 @@ +import * as types from 'constants/action-types'; + +import ungitConfig from 'reducers/ungit-config'; + +describe('ungit-config.js reducers', () => { + let initialState; + + it('should return original state if action doesn\'t match any case' , function() { + const state = ungitConfig(initialState, { type: types.NO_OP }); + expect(state).toEqual({}); + }); + + describe('when FETCH_UNGIT_CONFIG_SUCCESS action dispatch', () => { + it('state should have ungit configuration correctly', function() { + // TODO: consider to use sinon to mock data and make mock data reuseable and meaningful + const action = { type: types.FETCH_UNGIT_CONFIG_SUCCESS, payload: { + config: { + allowCheckoutNodes: false, + autoStashAndPop: true + }, + platform: 'darwin', + userHash: '69d23970c3b39b2a8d68a70c30cab99a2bf46e74', + version: 'dev-1.1.16-071f30a', + pluginApiVersion: '0.2.0' + } }; + + const state = ungitConfig(initialState, action); + expect(JSON.stringify(state)).toEqual(JSON.stringify(action.payload)); + }); + }); + +}); \ No newline at end of file diff --git a/src-react/__tests__/reducers/user-config.test.js b/src-react/__tests__/reducers/user-config.test.js new file mode 100644 index 0000000..ca16608 --- /dev/null +++ b/src-react/__tests__/reducers/user-config.test.js @@ -0,0 +1,26 @@ +import * as types from 'constants/action-types'; + +import userConfig from 'reducers/user-config'; + +describe('user-config.js reducers', () => { + let initialState; + + it('should return original state if action doesn\'t match any case' , () => { + const state = userConfig(initialState, { type: types.NO_OP }); + expect(state).toEqual({}); + }); + + describe('when FETCH_USER_CONFIG_SUCCESS action dispatch', () => { + it('state should have user configuration correctly', () => { + // TODO: consider to use sinon to mock data and make mock data reuseable and meaningful + const action = { type: types.FETCH_USER_CONFIG_SUCCESS, payload: { + port: 8080, + bugtracking: true + } }; + + const state = userConfig(initialState, action); + expect(JSON.stringify(state)).toEqual(JSON.stringify(action.payload)); + }); + }); + +}); \ No newline at end of file diff --git a/src-react/__tests__/reducers/versions.test.js b/src-react/__tests__/reducers/versions.test.js new file mode 100644 index 0000000..2697620 --- /dev/null +++ b/src-react/__tests__/reducers/versions.test.js @@ -0,0 +1,44 @@ +import * as types from 'constants/action-types'; + +import versions from 'reducers/versions'; + +describe('versions.js reducers', () => { + const initialState = { + gitVersion: null, + latestVersion: null + }; + + it('should return original state if action doesn\'t match any case' , () => { + const state = versions(initialState, { type: types.NO_OP }); + expect(state).toEqual(initialState); + }); + + describe('when FETCH_GIT_VERSION_SUCCESS action dispatch', () => { + it('state should have git version configuration correctly', () => { + // TODO: consider to use sinon to mock data and make mock data reuseable and meaningful + const action = { type: types.FETCH_GIT_VERSION_SUCCESS, payload: { + requiredVersion: '>=1.8.x', + satisfied: true, + version: '2.3.2' + } }; + + const state = versions(initialState, action); + expect(JSON.stringify(state.gitVersion)).toEqual(JSON.stringify(action.payload)); + }); + }); + + describe('when FETCH_LATEST_VERSION_SUCCESS action dispatch', () => { + it('state should have lastest configuration correctly', () => { + // TODO: consider to use sinon to mock data and make mock data reuseable and meaningful + const action = { type: types.FETCH_LATEST_VERSION_SUCCESS, payload: { + currentVersion: 'dev-1.1.16-071f30a', + latestVersion: '1.1.19', + outdated: false + } }; + + const state = versions(initialState, action); + expect(JSON.stringify(state.latestVersion)).toEqual(JSON.stringify(action.payload)); + }); + }); + +}); \ No newline at end of file diff --git a/src-react/actions/bootstrap.js b/src-react/actions/bootstrap.js index 582d442..e00fa2d 100644 --- a/src-react/actions/bootstrap.js +++ b/src-react/actions/bootstrap.js @@ -1,12 +1,11 @@ +import * as types from 'constants/action-types'; import { fetchUngitConfig } from './ungit-config'; +import store from 'store'; import { fetchLatestVersion, fetchGitVersion } from './version'; -import { pending } from './common'; export function bootstrap() { - return dispatch => { - dispatch(pending(3)); - dispatch(fetchUngitConfig()); - dispatch(fetchLatestVersion()); - dispatch(fetchGitVersion()); - }; + store.dispatch(fetchUngitConfig()); + store.dispatch(fetchLatestVersion()); + store.dispatch(fetchGitVersion()); + return { type: types.NO_OP }; } \ No newline at end of file diff --git a/src-react/actions/common.js b/src-react/actions/common.js deleted file mode 100644 index de1a3c2..0000000 --- a/src-react/actions/common.js +++ /dev/null @@ -1,16 +0,0 @@ -/* This export common using actionCreator */ -import * as types from 'constants/action-types'; - -export function pending(count) { - return { - type: types.PATH_PAGE_PENDING, - payload: count || 1 - }; -}; - -export function apiError(message) { - return { - type: types.PATH_PAGE_API_ERR, - payload: message - }; -} \ No newline at end of file diff --git a/src-react/actions/ungit-config.js b/src-react/actions/ungit-config.js index de55431..ce346fa 100644 --- a/src-react/actions/ungit-config.js +++ b/src-react/actions/ungit-config.js @@ -1,29 +1,24 @@ import * as types from 'constants/action-types'; +import { CALL_API } from 'redux-api-middleware'; import { fetchUserConfig } from './user-config'; -import { apiError, pending } from './common'; +import store from 'store'; export function fetchUngitConfig() { - return dispatch => { - // consider wrap API call in separate modules - // it will be easy to stub module's function when testing - fetch('http://localhost:8448/ungit/config') - .then(response => response.json()) - .then(json => { - if (!json.config.bugtracking) { - dispatch(pending()); - dispatch(fetchUserConfig()); - } - dispatch(receiveUngitConfig(json)); - }) - .catch(e => { - dispatch(apiError(e.message)); - }); - }; -}; - -function receiveUngitConfig(ungitConfig) { return { - type: types.RECEIVE_UNGIT_CONFIG, - payload: ungitConfig + [CALL_API]: { + endpoint: 'http://localhost:8448/ungit/config', + method: 'GET', + types: [ + types.FETCH_UNGIT_CONFIG_REQUEST, + { + type: types.FETCH_UNGIT_CONFIG_SUCCESS, + payload: (action, state, res) => { + store.dispatch(fetchUserConfig()); + return res.json().then(json => json); + } + }, + types.FETCH_UNGIT_CONFIG_FAILURE + ] + } }; -}; \ No newline at end of file +}; diff --git a/src-react/actions/user-config.js b/src-react/actions/user-config.js index 03f71a6..62d0772 100644 --- a/src-react/actions/user-config.js +++ b/src-react/actions/user-config.js @@ -1,25 +1,16 @@ import * as types from 'constants/action-types'; -import { apiError } from './common'; +import { CALL_API } from 'redux-api-middleware'; export function fetchUserConfig() { - return dispatch => { - // consider wrap API call in separate modules - // it will be easy to stub module's function when testing - fetch('http://localhost:8448/api/userconfig') - .then(response => response.json()) - .then(json => { - dispatch(receiveUserConfig(json)); - }) - .catch(e => { - dispatch(apiError(e.message)); - }); - }; -}; - - -function receiveUserConfig(userConfig) { return { - type: types.RECEIVE_USER_CONFIG, - payload: userConfig + [CALL_API]: { + endpoint: 'http://localhost:8448/api/userconfig', + method: 'GET', + types: [ + types.FETCH_USER_CONFIG_REQUEST, + types.FETCH_USER_CONFIG_SUCCESS, + types.FETCH_USER_CONFIG_FAILURE + ] + } }; }; \ No newline at end of file diff --git a/src-react/actions/version.js b/src-react/actions/version.js index a4c53fb..dabde16 100644 --- a/src-react/actions/version.js +++ b/src-react/actions/version.js @@ -1,46 +1,30 @@ import * as types from 'constants/action-types'; -import { apiError } from './common'; +import { CALL_API } from 'redux-api-middleware'; export function fetchLatestVersion() { - return dispatch => { - // consider wrap API call in separate modules - // it will be easy to stub module's function when testing - fetch('http://localhost:8448/api/latestversion') - .then(response => response.json()) - .then(json => { - dispatch(receiveLatestVersion(json)); - }) - .catch(e => { - dispatch(apiError(e.message)); - }); + return { + [CALL_API]: { + endpoint: 'http://localhost:8448/api/latestversion', + method: 'GET', + types: [ + types.FETCH_LATEST_VERSION_REQUEST, + types.FETCH_LATEST_VERSION_SUCCESS, + types.FETCH_LATEST_VERSION_FAILURE + ] + } }; } export function fetchGitVersion() { - return dispatch => { - // consider wrap API call in separate modules - // it will be easy to stub module's function when testing - fetch('http://localhost:8448/api/gitversion') - .then(response => response.json()) - .then(json => { - dispatch(receiveGitVersion(json)); - }) - .catch(e => { - dispatch(apiError(e.message)); - }); - }; -} - -function receiveGitVersion(gitVersion) { return { - type: types.RECEIVE_GIT_VERSION, - payload: gitVersion + [CALL_API]: { + endpoint: 'http://localhost:8448/api/gitversion', + method: 'GET', + types: [ + types.FETCH_GIT_VERSION_REQUEST, + types.FETCH_GIT_VERSION_SUCCESS, + types.FETCH_GIT_VERSION_FAILURE + ] + } }; } - -function receiveLatestVersion(latestVersion) { - return { - type: types.RECEIVE_LATEST_VERSION, - payload: latestVersion - }; -}; \ No newline at end of file diff --git a/src-react/constants/action-types.js b/src-react/constants/action-types.js index 69ec0e4..a7c12c1 100644 --- a/src-react/constants/action-types.js +++ b/src-react/constants/action-types.js @@ -1,6 +1,16 @@ -export const RECEIVE_GIT_VERSION = 'RECEIVE_GIT_VERSION'; -export const RECEIVE_LATEST_VERSION = 'RECEIVE_LATEST_VERSION'; -export const RECEIVE_USER_CONFIG = 'RECEIVE_USER_CONFIG'; -export const RECEIVE_UNGIT_CONFIG = 'RECEIVE_UNGIT_CONFIG'; -export const PATH_PAGE_PENDING = 'PATH_PAGE_PENDING'; -export const PATH_PAGE_API_ERR = 'PATH_PAGE_API_ERR'; \ No newline at end of file +export const NO_OP = 'no-op'; + +export const FETCH_USER_CONFIG_REQUEST = 'FETCH_USER_CONFIG_REQUEST'; +export const FETCH_LATEST_VERSION_REQUEST = 'FETCH_LATEST_VERSION_REQUEST'; +export const FETCH_GIT_VERSION_REQUEST = 'FETCH_GIT_VERSION_REQUEST'; +export const FETCH_UNGIT_CONFIG_REQUEST = 'FETCH_UNGIT_CONFIG_REQUEST'; + +export const FETCH_USER_CONFIG_FAILURE = 'FETCH_USER_CONFIG_FAILURE'; +export const FETCH_LATEST_VERSION_FAILURE = 'FETCH_LATEST_VERSION_FAILURE'; +export const FETCH_GIT_VERSION_FAILURE = 'FETCH_GIT_VERSION_FAILURE'; +export const FETCH_UNGIT_CONFIG_FAILURE = 'FETCH_UNGIT_CONFIG_FAILURE'; + +export const FETCH_USER_CONFIG_SUCCESS = 'FETCH_USER_CONFIG_SUCCESS'; +export const FETCH_LATEST_VERSION_SUCCESS = 'FETCH_LATEST_VERSION_SUCCESS'; +export const FETCH_GIT_VERSION_SUCCESS = 'FETCH_GIT_VERSION_SUCCESS'; +export const FETCH_UNGIT_CONFIG_SUCCESS = 'FETCH_UNGIT_CONFIG_SUCCESS'; \ No newline at end of file diff --git a/src-react/reducers/app.js b/src-react/reducers/app.js index 52c889e..18e94be 100644 --- a/src-react/reducers/app.js +++ b/src-react/reducers/app.js @@ -3,25 +3,25 @@ import * as types from 'constants/action-types'; function app(state, action, config) { switch(action.type) { - case types.RECEIVE_UNGIT_CONFIG: { + case types.FETCH_UNGIT_CONFIG_SUCCESS: { const { ungitConfig } = config; - const bugtrackingNagscreenDismissed = localStorage.getItem('bugtrackingNagscreenDismissed'); + const bugtrackingNagscreenDismissed = localStorage.getItem('bugtrackingNagscreenDismissed') === 'true'; const showBugtrackingNagscreen = !ungitConfig.config.bugtracking && !bugtrackingNagscreenDismissed; return { ...state, showBugtrackingNagscreen }; } - case types.RECEIVE_GIT_VERSION: { + case types.FETCH_GIT_VERSION_SUCCESS: { const { ungitConfig, versions: { gitVersion } } = config; const gitVersionCheckOverride = ungitConfig.config && ungitConfig.config.gitVersionCheckOverride; - const gitVersionErrorDismissed = localStorage.getItem('gitVersionErrorDismissed'); + const gitVersionErrorDismissed = localStorage.getItem('gitVersionErrorDismissed') === 'true'; const gitVersionError = gitVersion && !gitVersion.satisfied && gitVersion.error; - const gitVersionErrorVisible = !gitVersionCheckOverride && gitVersionError && gitVersionErrorDismissed; + const gitVersionErrorVisible = !gitVersionCheckOverride && gitVersionError && !gitVersionErrorDismissed; return { ...state, gitVersionErrorVisible }; } - case types.RECEIVE_LATEST_VERSION: { + case types.FETCH_LATEST_VERSION_SUCCESS: { const { ungitConfig, versions: { latestVersion } } = config; const gitVersionCheckOverride = ungitConfig.config && ungitConfig.config.gitVersionCheckOverride; const outdated = latestVersion && latestVersion.outdated; @@ -30,9 +30,9 @@ function app(state, action, config) { return { ...state, showNewVersionAvailable }; } - case types.RECEIVE_USER_CONFIG: { + case types.FETCH_USER_CONFIG_SUCCESS: { const { userConfig } = config; - const bugtrackingNagscreenDismissed = localStorage.getItem('bugtrackingNagscreenDismissed'); + const bugtrackingNagscreenDismissed = localStorage.getItem('bugtrackingNagscreenDismissed') === 'true'; const showBugtrackingNagscreen = !userConfig.bugtracking && !bugtrackingNagscreenDismissed; return { ...state, showBugtrackingNagscreen }; diff --git a/src-react/reducers/path.js b/src-react/reducers/path.js index f3d3469..42b312d 100644 --- a/src-react/reducers/path.js +++ b/src-react/reducers/path.js @@ -2,16 +2,22 @@ import * as types from 'constants/action-types'; function path(state, action) { switch(action.type) { - case types.PATH_PAGE_PENDING: - return { ...state, pending: state.pending + action.payload }; - case types.RECEIVE_UNGIT_CONFIG: - case types.RECEIVE_USER_CONFIG: - case types.RECEIVE_GIT_VERSION: - case types.RECEIVE_LATEST_VERSION: + case types.FETCH_USER_CONFIG_REQUEST: + case types.FETCH_LATEST_VERSION_REQUEST: + case types.FETCH_GIT_VERSION_REQUEST: + case types.FETCH_UNGIT_CONFIG_REQUEST: + return { ...state, pending: state.pending + 1 }; + case types.FETCH_USER_CONFIG_FAILURE: + case types.FETCH_LATEST_VERSION_FAILURE: + case types.FETCH_GIT_VERSION_FAILURE: + case types.FETCH_UNGIT_CONFIG_FAILURE: + const { payload: { message } } = action; + return { ...state, pending: state.pending - 1, errMessage: [ ...state.errMessage, message ] }; + case types.FETCH_USER_CONFIG_SUCCESS: + case types.FETCH_LATEST_VERSION_SUCCESS: + case types.FETCH_GIT_VERSION_SUCCESS: + case types.FETCH_UNGIT_CONFIG_SUCCESS: return { ...state, pending: state.pending - 1 }; - case types.PATH_PAGE_API_ERR: - const { payload: errMessage } = action; - return { ...state, pending: state.pending - 1, errMessage: [ ...state.errMessage, errMessage ] }; default: return { ...state }; } diff --git a/src-react/reducers/ungit-config.js b/src-react/reducers/ungit-config.js index 6bbac31..2debeca 100644 --- a/src-react/reducers/ungit-config.js +++ b/src-react/reducers/ungit-config.js @@ -2,7 +2,7 @@ import * as types from 'constants/action-types'; function ungitConfig(state, action) { switch(action.type) { - case types.RECEIVE_UNGIT_CONFIG: + case types.FETCH_UNGIT_CONFIG_SUCCESS: const { payload: ungitConfig } = action; return { ...ungitConfig }; default: diff --git a/src-react/reducers/user-config.js b/src-react/reducers/user-config.js index 23f3b65..6098d30 100644 --- a/src-react/reducers/user-config.js +++ b/src-react/reducers/user-config.js @@ -2,7 +2,7 @@ import * as types from 'constants/action-types'; function userConfig(state, action) { switch(action.type) { - case types.RECEIVE_USER_CONFIG: + case types.FETCH_USER_CONFIG_SUCCESS: const { payload: userConfig } = action; return { ...userConfig }; default: diff --git a/src-react/reducers/versions.js b/src-react/reducers/versions.js index 9ddae17..1c53c7c 100644 --- a/src-react/reducers/versions.js +++ b/src-react/reducers/versions.js @@ -1,11 +1,11 @@ import * as types from 'constants/action-types'; -function userConfig(state, action) { +function versions(state, action) { switch(action.type) { - case types.RECEIVE_GIT_VERSION: + case types.FETCH_GIT_VERSION_SUCCESS: const { payload: gitVersion } = action; return { ...state, gitVersion }; - case types.RECEIVE_LATEST_VERSION: + case types.FETCH_LATEST_VERSION_SUCCESS: const { payload: latestVersion } = action; return { ...state, latestVersion }; default: @@ -13,4 +13,4 @@ function userConfig(state, action) { } } -export default userConfig; \ No newline at end of file +export default versions; \ No newline at end of file diff --git a/src-react/store.js b/src-react/store.js index 88a8839..0b3ac13 100644 --- a/src-react/store.js +++ b/src-react/store.js @@ -1,7 +1,9 @@ import { createStore, applyMiddleware } from 'redux'; -import thunk from 'redux-thunk'; +import { apiMiddleware } from 'redux-api-middleware'; import ungitApp from './reducers'; +// const middlewares = [thunk, fetchMiddleware]; + const initialState = { config: { ungitConfig: null, @@ -23,6 +25,6 @@ const initialState = { } }; -const store = createStore(ungitApp, initialState, applyMiddleware(thunk)); +const store = createStore(ungitApp, initialState, applyMiddleware(apiMiddleware)); export default store; \ No newline at end of file