mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-03 23:07:26 +03:00
Merge pull request #166 from acelaya-forks/feature/fix-create-short-url
Ensured server version is properly parsed to avoid errors due to inva…
This commit is contained in:
commit
e9fc2bb73a
4 changed files with 67 additions and 13 deletions
23
CHANGELOG.md
23
CHANGELOG.md
|
@ -4,6 +4,29 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
|
## 2.2.1 - 2019-10-18
|
||||||
|
|
||||||
|
#### Added
|
||||||
|
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
#### Changed
|
||||||
|
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
#### Deprecated
|
||||||
|
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
#### Removed
|
||||||
|
|
||||||
|
* *Nothing*
|
||||||
|
|
||||||
|
#### Fixed
|
||||||
|
|
||||||
|
* [#165](https://github.com/shlinkio/shlink-web-client/issues/165) Fixed error thrown when opening "create" page while using a Shlink version which does not return a valid SemVer version (like `latest` docker image, or any development instance).
|
||||||
|
|
||||||
|
|
||||||
## 2.2.0 - 2019-10-05
|
## 2.2.0 - 2019-10-05
|
||||||
|
|
||||||
#### Added
|
#### Added
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
import { createAction, handleActions } from 'redux-actions';
|
import { createAction, handleActions } from 'redux-actions';
|
||||||
import { resetShortUrlParams } from '../../short-urls/reducers/shortUrlsListParams';
|
import { resetShortUrlParams } from '../../short-urls/reducers/shortUrlsListParams';
|
||||||
|
import { versionIsValidSemVer } from '../../utils/utils';
|
||||||
|
|
||||||
/* eslint-disable padding-line-between-statements */
|
/* eslint-disable padding-line-between-statements */
|
||||||
export const SELECT_SERVER = 'shlink/selectedServer/SELECT_SERVER';
|
export const SELECT_SERVER = 'shlink/selectedServer/SELECT_SERVER';
|
||||||
export const RESET_SELECTED_SERVER = 'shlink/selectedServer/RESET_SELECTED_SERVER';
|
export const RESET_SELECTED_SERVER = 'shlink/selectedServer/RESET_SELECTED_SERVER';
|
||||||
|
|
||||||
|
export const MIN_FALLBACK_VERSION = '1.0.0';
|
||||||
|
export const MAX_FALLBACK_VERSION = '999.999.999';
|
||||||
|
export const LATEST_VERSION_CONSTRAINT = 'latest';
|
||||||
/* eslint-enable padding-line-between-statements */
|
/* eslint-enable padding-line-between-statements */
|
||||||
|
|
||||||
const initialState = null;
|
const initialState = null;
|
||||||
|
@ -15,7 +20,10 @@ export const selectServer = ({ findServerById }, buildShlinkApiClient) => (serve
|
||||||
|
|
||||||
const selectedServer = findServerById(serverId);
|
const selectedServer = findServerById(serverId);
|
||||||
const { health } = await buildShlinkApiClient(selectedServer);
|
const { health } = await buildShlinkApiClient(selectedServer);
|
||||||
const { version } = await health().catch(() => ({ version: '1.0.0' }));
|
const version = await health()
|
||||||
|
.then(({ version }) => version === LATEST_VERSION_CONSTRAINT ? MAX_FALLBACK_VERSION : version)
|
||||||
|
.then((version) => !versionIsValidSemVer(version) ? MIN_FALLBACK_VERSION : version)
|
||||||
|
.catch(() => MIN_FALLBACK_VERSION);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: SELECT_SERVER,
|
type: SELECT_SERVER,
|
||||||
|
|
|
@ -60,3 +60,11 @@ export const compareVersions = (firstVersion, operator, secondVersion) => compar
|
||||||
secondVersion,
|
secondVersion,
|
||||||
operator
|
operator
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const versionIsValidSemVer = (version) => {
|
||||||
|
try {
|
||||||
|
return compareVersions(version, '=', version);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
import each from 'jest-each';
|
||||||
import reducer, {
|
import reducer, {
|
||||||
selectServer,
|
selectServer,
|
||||||
resetSelectedServer,
|
resetSelectedServer,
|
||||||
RESET_SELECTED_SERVER,
|
RESET_SELECTED_SERVER,
|
||||||
SELECT_SERVER,
|
SELECT_SERVER,
|
||||||
|
MAX_FALLBACK_VERSION,
|
||||||
|
MIN_FALLBACK_VERSION,
|
||||||
} from '../../../src/servers/reducers/selectedServer';
|
} from '../../../src/servers/reducers/selectedServer';
|
||||||
import { RESET_SHORT_URL_PARAMS } from '../../../src/short-urls/reducers/shortUrlsListParams';
|
import { RESET_SHORT_URL_PARAMS } from '../../../src/short-urls/reducers/shortUrlsListParams';
|
||||||
|
|
||||||
|
@ -34,26 +37,25 @@ describe('selectedServerReducer', () => {
|
||||||
findServerById: jest.fn(() => selectedServer),
|
findServerById: jest.fn(() => selectedServer),
|
||||||
};
|
};
|
||||||
const apiClientMock = {
|
const apiClientMock = {
|
||||||
health: jest.fn().mockResolvedValue({ version }),
|
health: jest.fn(),
|
||||||
};
|
};
|
||||||
const buildApiClient = jest.fn().mockResolvedValue(apiClientMock);
|
const buildApiClient = jest.fn().mockResolvedValue(apiClientMock);
|
||||||
|
const dispatch = jest.fn();
|
||||||
|
|
||||||
beforeEach(() => {
|
afterEach(jest.clearAllMocks);
|
||||||
apiClientMock.health.mockClear();
|
|
||||||
buildApiClient.mockClear();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
each([
|
||||||
ServersServiceMock.findServerById.mockClear();
|
[ version, version ],
|
||||||
});
|
[ 'latest', MAX_FALLBACK_VERSION ],
|
||||||
|
[ '%invalid_semver%', MIN_FALLBACK_VERSION ],
|
||||||
it('dispatches proper actions', async () => {
|
]).it('dispatches proper actions', async (serverVersion, expectedVersion) => {
|
||||||
const dispatch = jest.fn();
|
|
||||||
const expectedSelectedServer = {
|
const expectedSelectedServer = {
|
||||||
...selectedServer,
|
...selectedServer,
|
||||||
version,
|
version: expectedVersion,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
apiClientMock.health.mockResolvedValue({ version: serverVersion });
|
||||||
|
|
||||||
await selectServer(ServersServiceMock, buildApiClient)(serverId)(dispatch);
|
await selectServer(ServersServiceMock, buildApiClient)(serverId)(dispatch);
|
||||||
|
|
||||||
expect(dispatch).toHaveBeenCalledTimes(2);
|
expect(dispatch).toHaveBeenCalledTimes(2);
|
||||||
|
@ -67,5 +69,18 @@ describe('selectedServerReducer', () => {
|
||||||
expect(ServersServiceMock.findServerById).toHaveBeenCalledTimes(1);
|
expect(ServersServiceMock.findServerById).toHaveBeenCalledTimes(1);
|
||||||
expect(buildApiClient).toHaveBeenCalledTimes(1);
|
expect(buildApiClient).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('falls back to min version when health endpoint fails', async () => {
|
||||||
|
const expectedSelectedServer = {
|
||||||
|
...selectedServer,
|
||||||
|
version: MIN_FALLBACK_VERSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
apiClientMock.health.mockRejectedValue({});
|
||||||
|
|
||||||
|
await selectServer(ServersServiceMock, buildApiClient)(serverId)(dispatch);
|
||||||
|
|
||||||
|
expect(dispatch).toHaveBeenNthCalledWith(2, { type: SELECT_SERVER, selectedServer: expectedSelectedServer });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue