[CHORE] Example of actions & thunks specs

This commit is contained in:
Oleg Shuralev 2021-02-19 01:42:08 +03:00
parent 605c354b01
commit fcea2952c5
No known key found for this signature in database
GPG key ID: 99C6BDC0A1C2E647
5 changed files with 234 additions and 10 deletions

View file

@ -2720,8 +2720,28 @@
"@types/node": {
"version": "12.19.15",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.15.tgz",
"integrity": "sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw==",
"dev": true
"integrity": "sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw=="
},
"@types/node-fetch": {
"version": "2.5.8",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz",
"integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==",
"requires": {
"@types/node": "*",
"form-data": "^3.0.0"
},
"dependencies": {
"form-data": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
}
}
},
"@types/normalize-package-data": {
"version": "2.4.0",
@ -2824,6 +2844,15 @@
"redux": "*"
}
},
"@types/redux-mock-store": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/redux-mock-store/-/redux-mock-store-1.0.2.tgz",
"integrity": "sha512-6LBtAQBN34i7SI5X+Qs4zpTEZO1tTDZ6sZ9fzFjYwTl3nLQXaBtwYdoV44CzNnyKu438xJ1lSIYyw0YMvunESw==",
"dev": true,
"requires": {
"redux": "^4.0.5"
}
},
"@types/redux-thunk": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/redux-thunk/-/redux-thunk-2.1.0.tgz",
@ -4084,8 +4113,7 @@
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
"dev": true
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"at-least-node": {
"version": "1.0.0",
@ -5563,7 +5591,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dev": true,
"requires": {
"delayed-stream": "~1.0.0"
}
@ -6512,8 +6539,7 @@
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"dev": true
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"delegates": {
"version": "1.0.0",
@ -8201,6 +8227,82 @@
"bser": "2.1.1"
}
},
"fetch-mock": {
"version": "9.11.0",
"resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-9.11.0.tgz",
"integrity": "sha512-PG1XUv+x7iag5p/iNHD4/jdpxL9FtVSqRMUQhPab4hVDt80T1MH5ehzVrL2IdXO9Q2iBggArFvPqjUbHFuI58Q==",
"dev": true,
"requires": {
"@babel/core": "^7.0.0",
"@babel/runtime": "^7.0.0",
"core-js": "^3.0.0",
"debug": "^4.1.1",
"glob-to-regexp": "^0.4.0",
"is-subset": "^0.1.1",
"lodash.isequal": "^4.5.0",
"path-to-regexp": "^2.2.1",
"querystring": "^0.2.0",
"whatwg-url": "^6.5.0"
},
"dependencies": {
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"requires": {
"ms": "2.1.2"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"path-to-regexp": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz",
"integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==",
"dev": true
},
"tr46": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
"integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
"dev": true,
"requires": {
"punycode": "^2.1.0"
}
},
"webidl-conversions": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
"dev": true
},
"whatwg-url": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz",
"integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==",
"dev": true,
"requires": {
"lodash.sortby": "^4.7.0",
"tr46": "^1.0.1",
"webidl-conversions": "^4.0.2"
}
}
}
},
"fetch-mock-jest": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/fetch-mock-jest/-/fetch-mock-jest-1.5.1.tgz",
"integrity": "sha512-+utwzP8C+Pax1GSka3nFXILWMY3Er2L+s090FOgqVNrNCPp0fDqgXnAHAJf12PLHi0z4PhcTaZNTz8e7K3fjqQ==",
"dev": true,
"requires": {
"fetch-mock": "^9.11.0"
}
},
"figgy-pudding": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
@ -8931,6 +9033,12 @@
"is-glob": "^4.0.1"
}
},
"glob-to-regexp": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
"dev": true
},
"global-modules": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
@ -12063,6 +12171,12 @@
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
"dev": true
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=",
"dev": true
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@ -12446,14 +12560,12 @@
"mime-db": {
"version": "1.45.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
"integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==",
"dev": true
"integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w=="
},
"mime-types": {
"version": "2.1.28",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz",
"integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==",
"dev": true,
"requires": {
"mime-db": "1.45.0"
}
@ -12799,6 +12911,11 @@
"dev": true,
"optional": true
},
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
"node-forge": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
@ -16004,6 +16121,15 @@
"symbol-observable": "^1.2.0"
}
},
"redux-mock-store": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/redux-mock-store/-/redux-mock-store-1.5.4.tgz",
"integrity": "sha512-xmcA0O/tjCLXhh9Fuiq6pMrJCwFRaouA8436zcikdIpYWWCjU76CRk+i2bHx8EeiSiMGnB85/lZdU3wIJVXHTA==",
"dev": true,
"requires": {
"lodash.isplainobject": "^4.0.6"
}
},
"redux-thunk": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",

View file

@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@types/node-fetch": "^2.5.8",
"bulma": "^0.9.2",
"bulma-switch": "^2.0.0",
"classnames": "^2.2.6",
@ -11,6 +12,7 @@
"eslint-import-resolver-typescript": "^2.3.0",
"immer": "^8.0.1",
"lodash": "^4.17.20",
"node-fetch": "^2.6.1",
"pretty-ms": "^6.0.1",
"react": "^17.0.1",
"react-datepicker": "^3.3.0",
@ -80,6 +82,7 @@
"@types/react-redux": "^7.1.11",
"@types/react-router-dom": "^5.1.6",
"@types/redux": "^3.6.0",
"@types/redux-mock-store": "^1.0.2",
"@types/redux-thunk": "^2.1.0",
"@types/uuid": "^8.3.0",
"@typescript-eslint/eslint-plugin": "^4.9.0",
@ -98,11 +101,13 @@
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^2.5.1",
"esprint": "^0.6.0",
"fetch-mock-jest": "^1.5.1",
"husky": "^4.3.0",
"lint-staged": "^10.5.2",
"node-sass": "^4.14.1",
"prettier": "^2.2.1",
"react-scripts": "4.0.2",
"redux-mock-store": "^1.5.4",
"ts-jest": "^26.4.4",
"ts-node": "^9.1.1",
"typescript": "~4.1.2"

View file

@ -0,0 +1,28 @@
import * as actions from '../actions';
describe('Actions', () => {
describe('fetchClusterStatsAction', () => {
it('creates an REQUEST action', () => {
expect(actions.fetchClusterStatsAction.request()).toEqual({
type: 'GET_CLUSTER_STATUS__REQUEST',
});
});
it('creates an SUCCESS action', () => {
expect(
actions.fetchClusterStatsAction.success({ brokerCount: 1 })
).toEqual({
type: 'GET_CLUSTER_STATUS__SUCCESS',
payload: {
brokerCount: 1,
},
});
});
it('creates an FAILURE action', () => {
expect(actions.fetchClusterStatsAction.failure()).toEqual({
type: 'GET_CLUSTER_STATUS__FAILURE',
});
});
});
});

View file

@ -0,0 +1,13 @@
import { ClusterStats } from 'generated-sources';
export const clusterStats: ClusterStats = {
brokerCount: 1,
zooKeeperStatus: 1,
activeControllers: 1,
onlinePartitionCount: 6,
offlinePartitionCount: 0,
inSyncReplicasCount: 6,
outOfSyncReplicasCount: 0,
underReplicatedPartitionCount: 0,
diskUsage: [{ brokerId: 1, segmentSize: 6538, segmentCount: 6 }],
};

View file

@ -0,0 +1,52 @@
import configureMockStore, {
MockStoreCreator,
MockStoreEnhanced,
} from 'redux-mock-store';
import thunk, { ThunkDispatch } from 'redux-thunk';
import fetchMock from 'fetch-mock-jest';
import { Middleware } from 'redux';
import { RootState, Action } from 'redux/interfaces';
import * as actions from 'redux/actions/actions';
import * as thunks from 'redux/actions/thunks';
import * as fixtures from './fixtures';
const middlewares: Array<Middleware> = [thunk];
type DispatchExts = ThunkDispatch<RootState, undefined, Action>;
const mockStoreCreator: MockStoreCreator<
RootState,
DispatchExts
> = configureMockStore<RootState, DispatchExts>(middlewares);
const store: MockStoreEnhanced<RootState, DispatchExts> = mockStoreCreator();
const clusterName = 'local';
describe('Thunks', () => {
afterEach(() => {
fetchMock.restore();
store.clearActions();
});
describe('fetchClusterStats', () => {
it('creates GET_CLUSTER_STATUS__SUCCESS when fetching cluster stats', async () => {
fetchMock.getOnce(`/api/clusters/${clusterName}/stats`, {
body: fixtures.clusterStats,
});
await store.dispatch(thunks.fetchClusterStats(clusterName));
expect(store.getActions()).toEqual([
actions.fetchClusterStatsAction.request(),
actions.fetchClusterStatsAction.success(fixtures.clusterStats),
]);
});
it('creates GET_CLUSTER_STATUS__FAILURE when fetching cluster stats', async () => {
fetchMock.getOnce(`/api/clusters/${clusterName}/stats`, 404);
await store.dispatch(thunks.fetchClusterStats(clusterName));
expect(store.getActions()).toEqual([
actions.fetchClusterStatsAction.request(),
actions.fetchClusterStatsAction.failure(),
]);
});
});
});