mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-03-17 13:03:50 +00:00
Created mercure info reducer and loaded info when server is reachable
This commit is contained in:
@@ -9,6 +9,7 @@ import provideServersServices from '../servers/services/provideServices';
|
|||||||
import provideVisitsServices from '../visits/services/provideServices';
|
import provideVisitsServices from '../visits/services/provideServices';
|
||||||
import provideTagsServices from '../tags/services/provideServices';
|
import provideTagsServices from '../tags/services/provideServices';
|
||||||
import provideUtilsServices from '../utils/services/provideServices';
|
import provideUtilsServices from '../utils/services/provideServices';
|
||||||
|
import provideMercureServices from '../mercure/services/provideServices';
|
||||||
|
|
||||||
const bottle = new Bottle();
|
const bottle = new Bottle();
|
||||||
const { container } = bottle;
|
const { container } = bottle;
|
||||||
@@ -34,5 +35,6 @@ provideServersServices(bottle, connect, withRouter);
|
|||||||
provideTagsServices(bottle, connect);
|
provideTagsServices(bottle, connect);
|
||||||
provideVisitsServices(bottle, connect);
|
provideVisitsServices(bottle, connect);
|
||||||
provideUtilsServices(bottle);
|
provideUtilsServices(bottle);
|
||||||
|
provideMercureServices(bottle);
|
||||||
|
|
||||||
export default container;
|
export default container;
|
||||||
|
|||||||
41
src/mercure/reducers/mercureInfo.js
Normal file
41
src/mercure/reducers/mercureInfo.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { handleActions } from 'redux-actions';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
/* eslint-disable padding-line-between-statements */
|
||||||
|
export const GET_MERCURE_INFO_START = 'shlink/mercure/GET_MERCURE_INFO_START';
|
||||||
|
export const GET_MERCURE_INFO_ERROR = 'shlink/mercure/GET_MERCURE_INFO_ERROR';
|
||||||
|
export const GET_MERCURE_INFO = 'shlink/mercure/GET_MERCURE_INFO';
|
||||||
|
/* eslint-enable padding-line-between-statements */
|
||||||
|
|
||||||
|
export const MercureInfoType = PropTypes.shape({
|
||||||
|
token: PropTypes.string,
|
||||||
|
mercureHubUrl: PropTypes.string,
|
||||||
|
loading: PropTypes.bool,
|
||||||
|
error: PropTypes.bool,
|
||||||
|
});
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
token: undefined,
|
||||||
|
mercureHubUrl: undefined,
|
||||||
|
loading: false,
|
||||||
|
error: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default handleActions({
|
||||||
|
[GET_MERCURE_INFO_START]: (state) => ({ ...state, loading: true, error: false }),
|
||||||
|
[GET_MERCURE_INFO_ERROR]: (state) => ({ ...state, loading: false, error: true }),
|
||||||
|
[GET_MERCURE_INFO]: (state, { token, mercureHubUrl }) => ({ token, mercureHubUrl, loading: false, error: false }),
|
||||||
|
}, initialState);
|
||||||
|
|
||||||
|
export const loadMercureInfo = (buildShlinkApiClient) => () => async (dispatch, getState) => {
|
||||||
|
dispatch({ type: GET_MERCURE_INFO_START });
|
||||||
|
const { mercureInfo } = buildShlinkApiClient(getState);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await mercureInfo();
|
||||||
|
|
||||||
|
dispatch({ type: GET_MERCURE_INFO, ...result });
|
||||||
|
} catch (e) {
|
||||||
|
dispatch({ type: GET_MERCURE_INFO_ERROR });
|
||||||
|
}
|
||||||
|
};
|
||||||
8
src/mercure/services/provideServices.js
Normal file
8
src/mercure/services/provideServices.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { loadMercureInfo } from '../reducers/mercureInfo';
|
||||||
|
|
||||||
|
const provideServices = (bottle) => {
|
||||||
|
// Actions
|
||||||
|
bottle.serviceFactory('loadMercureInfo', loadMercureInfo, 'buildShlinkApiClient');
|
||||||
|
};
|
||||||
|
|
||||||
|
export default provideServices;
|
||||||
@@ -13,6 +13,7 @@ import shortUrlDetailReducer from '../visits/reducers/shortUrlDetail';
|
|||||||
import tagsListReducer from '../tags/reducers/tagsList';
|
import tagsListReducer from '../tags/reducers/tagsList';
|
||||||
import tagDeleteReducer from '../tags/reducers/tagDelete';
|
import tagDeleteReducer from '../tags/reducers/tagDelete';
|
||||||
import tagEditReducer from '../tags/reducers/tagEdit';
|
import tagEditReducer from '../tags/reducers/tagEdit';
|
||||||
|
import mercureInfoReducer from '../mercure/reducers/mercureInfo';
|
||||||
|
|
||||||
export default combineReducers({
|
export default combineReducers({
|
||||||
servers: serversReducer,
|
servers: serversReducer,
|
||||||
@@ -29,4 +30,5 @@ export default combineReducers({
|
|||||||
tagsList: tagsListReducer,
|
tagsList: tagsListReducer,
|
||||||
tagDelete: tagDeleteReducer,
|
tagDelete: tagDeleteReducer,
|
||||||
tagEdit: tagEditReducer,
|
tagEdit: tagEditReducer,
|
||||||
|
mercureInfo: mercureInfoReducer,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ const getServerVersion = memoizeWith(identity, (serverId, health) => health().th
|
|||||||
|
|
||||||
export const resetSelectedServer = createAction(RESET_SELECTED_SERVER);
|
export const resetSelectedServer = createAction(RESET_SELECTED_SERVER);
|
||||||
|
|
||||||
export const selectServer = ({ findServerById }, buildShlinkApiClient) => (serverId) => async (dispatch) => {
|
export const selectServer = ({ findServerById }, buildShlinkApiClient, loadMercureInfo) => (serverId) => async (
|
||||||
|
dispatch
|
||||||
|
) => {
|
||||||
dispatch(resetSelectedServer());
|
dispatch(resetSelectedServer());
|
||||||
dispatch(resetShortUrlParams());
|
dispatch(resetShortUrlParams());
|
||||||
const selectedServer = findServerById(serverId);
|
const selectedServer = findServerById(serverId);
|
||||||
@@ -51,6 +53,7 @@ export const selectServer = ({ findServerById }, buildShlinkApiClient) => (serve
|
|||||||
printableVersion,
|
printableVersion,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
dispatch(loadMercureInfo());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: SELECT_SERVER,
|
type: SELECT_SERVER,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const provideServices = (bottle, connect, withRouter) => {
|
|||||||
bottle.service('ServersExporter', ServersExporter, 'ServersService', 'window', 'csvjson');
|
bottle.service('ServersExporter', ServersExporter, 'ServersService', 'window', 'csvjson');
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
bottle.serviceFactory('selectServer', selectServer, 'ServersService', 'buildShlinkApiClient');
|
bottle.serviceFactory('selectServer', selectServer, 'ServersService', 'buildShlinkApiClient', 'loadMercureInfo');
|
||||||
bottle.serviceFactory('createServer', createServer, 'ServersService', 'listServers');
|
bottle.serviceFactory('createServer', createServer, 'ServersService', 'listServers');
|
||||||
bottle.serviceFactory('createServers', createServers, 'ServersService', 'listServers');
|
bottle.serviceFactory('createServers', createServers, 'ServersService', 'listServers');
|
||||||
bottle.serviceFactory('deleteServer', deleteServer, 'ServersService', 'listServers');
|
bottle.serviceFactory('deleteServer', deleteServer, 'ServersService', 'listServers');
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ export default class ShlinkApiClient {
|
|||||||
|
|
||||||
health = () => this._performRequest('/health', 'GET').then((resp) => resp.data);
|
health = () => this._performRequest('/health', 'GET').then((resp) => resp.data);
|
||||||
|
|
||||||
|
mercureInfo = () => this._performRequest('/mercure-info', 'GET').then((resp) => resp.data);
|
||||||
|
|
||||||
_performRequest = async (url, method = 'GET', query = {}, body = {}) => {
|
_performRequest = async (url, method = 'GET', query = {}, body = {}) => {
|
||||||
try {
|
try {
|
||||||
return await this.axios({
|
return await this.axios({
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ describe('selectedServerReducer', () => {
|
|||||||
};
|
};
|
||||||
const buildApiClient = jest.fn().mockReturnValue(apiClientMock);
|
const buildApiClient = jest.fn().mockReturnValue(apiClientMock);
|
||||||
const dispatch = jest.fn();
|
const dispatch = jest.fn();
|
||||||
|
const loadMercureInfo = jest.fn();
|
||||||
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
||||||
@@ -56,16 +57,17 @@ describe('selectedServerReducer', () => {
|
|||||||
|
|
||||||
apiClientMock.health.mockResolvedValue({ version: serverVersion });
|
apiClientMock.health.mockResolvedValue({ version: serverVersion });
|
||||||
|
|
||||||
await selectServer(ServersServiceMock, buildApiClient)(uuid())(dispatch);
|
await selectServer(ServersServiceMock, buildApiClient, loadMercureInfo)(uuid())(dispatch);
|
||||||
|
|
||||||
expect(dispatch).toHaveBeenCalledTimes(3);
|
expect(dispatch).toHaveBeenCalledTimes(4);
|
||||||
expect(dispatch).toHaveBeenNthCalledWith(1, { type: RESET_SELECTED_SERVER });
|
expect(dispatch).toHaveBeenNthCalledWith(1, { type: RESET_SELECTED_SERVER });
|
||||||
expect(dispatch).toHaveBeenNthCalledWith(2, { type: RESET_SHORT_URL_PARAMS });
|
expect(dispatch).toHaveBeenNthCalledWith(2, { type: RESET_SHORT_URL_PARAMS });
|
||||||
expect(dispatch).toHaveBeenNthCalledWith(3, { type: SELECT_SERVER, selectedServer: expectedSelectedServer });
|
expect(dispatch).toHaveBeenNthCalledWith(3, { type: SELECT_SERVER, selectedServer: expectedSelectedServer });
|
||||||
|
expect(loadMercureInfo).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invokes dependencies', async () => {
|
it('invokes dependencies', async () => {
|
||||||
await selectServer(ServersServiceMock, buildApiClient)(uuid())(() => {});
|
await selectServer(ServersServiceMock, buildApiClient, loadMercureInfo)(uuid())(() => {});
|
||||||
|
|
||||||
expect(ServersServiceMock.findServerById).toHaveBeenCalledTimes(1);
|
expect(ServersServiceMock.findServerById).toHaveBeenCalledTimes(1);
|
||||||
expect(buildApiClient).toHaveBeenCalledTimes(1);
|
expect(buildApiClient).toHaveBeenCalledTimes(1);
|
||||||
@@ -76,10 +78,11 @@ describe('selectedServerReducer', () => {
|
|||||||
|
|
||||||
apiClientMock.health.mockRejectedValue({});
|
apiClientMock.health.mockRejectedValue({});
|
||||||
|
|
||||||
await selectServer(ServersServiceMock, buildApiClient)(uuid())(dispatch);
|
await selectServer(ServersServiceMock, buildApiClient, loadMercureInfo)(uuid())(dispatch);
|
||||||
|
|
||||||
expect(apiClientMock.health).toHaveBeenCalled();
|
expect(apiClientMock.health).toHaveBeenCalled();
|
||||||
expect(dispatch).toHaveBeenNthCalledWith(3, { type: SELECT_SERVER, selectedServer: expectedSelectedServer });
|
expect(dispatch).toHaveBeenNthCalledWith(3, { type: SELECT_SERVER, selectedServer: expectedSelectedServer });
|
||||||
|
expect(loadMercureInfo).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('dispatches error when server is not found', async () => {
|
it('dispatches error when server is not found', async () => {
|
||||||
@@ -87,11 +90,12 @@ describe('selectedServerReducer', () => {
|
|||||||
|
|
||||||
ServersServiceMock.findServerById.mockReturnValue(undefined);
|
ServersServiceMock.findServerById.mockReturnValue(undefined);
|
||||||
|
|
||||||
await selectServer(ServersServiceMock, buildApiClient)(uuid())(dispatch);
|
await selectServer(ServersServiceMock, buildApiClient, loadMercureInfo)(uuid())(dispatch);
|
||||||
|
|
||||||
expect(ServersServiceMock.findServerById).toHaveBeenCalled();
|
expect(ServersServiceMock.findServerById).toHaveBeenCalled();
|
||||||
expect(apiClientMock.health).not.toHaveBeenCalled();
|
expect(apiClientMock.health).not.toHaveBeenCalled();
|
||||||
expect(dispatch).toHaveBeenNthCalledWith(3, { type: SELECT_SERVER, selectedServer: expectedSelectedServer });
|
expect(dispatch).toHaveBeenNthCalledWith(3, { type: SELECT_SERVER, selectedServer: expectedSelectedServer });
|
||||||
|
expect(loadMercureInfo).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -209,4 +209,20 @@ describe('ShlinkApiClient', () => {
|
|||||||
expect(result).toEqual(expectedData);
|
expect(result).toEqual(expectedData);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('mercureInfo', () => {
|
||||||
|
it('returns mercure info', async () => {
|
||||||
|
const expectedData = {
|
||||||
|
token: 'abc.123.def',
|
||||||
|
mercureHubUrl: 'http://example.com/.well-known/mercure',
|
||||||
|
};
|
||||||
|
const axiosSpy = jest.fn(createAxiosMock({ data: expectedData }));
|
||||||
|
const { mercureInfo } = new ShlinkApiClient(axiosSpy);
|
||||||
|
|
||||||
|
const result = await mercureInfo();
|
||||||
|
|
||||||
|
expect(axiosSpy).toHaveBeenCalled();
|
||||||
|
expect(result).toEqual(expectedData);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user