topics.spec.ts 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. import fetchMock from 'fetch-mock-jest';
  2. import * as actions from 'redux/actions/actions';
  3. import * as thunks from 'redux/actions/thunks';
  4. import mockStoreCreator from 'redux/store/configureStore/mockStoreCreator';
  5. import { mockTopicsState } from 'redux/actions/__test__/fixtures';
  6. import { MessageSchemaSourceEnum, TopicMessageSchema } from 'generated-sources';
  7. import { FailurePayload } from 'redux/interfaces';
  8. import { getResponse } from 'lib/errorHandling';
  9. import { internalTopicPayload } from 'redux/reducers/topics/__test__/fixtures';
  10. import { getAlertActions, getTypeAndPayload } from 'lib/testHelpers';
  11. const store = mockStoreCreator;
  12. const clusterName = 'local';
  13. const topicName = 'localTopic';
  14. describe('Thunks', () => {
  15. afterEach(() => {
  16. fetchMock.restore();
  17. store.clearActions();
  18. });
  19. describe('deleteTopis', () => {
  20. it('creates DELETE_TOPIC__SUCCESS when deleting existing topic', async () => {
  21. fetchMock.deleteOnce(
  22. `/api/clusters/${clusterName}/topics/${topicName}`,
  23. 200
  24. );
  25. await store.dispatch(thunks.deleteTopic(clusterName, topicName));
  26. expect(store.getActions()).toEqual([
  27. actions.deleteTopicAction.request(),
  28. actions.deleteTopicAction.success(topicName),
  29. ]);
  30. });
  31. it('creates DELETE_TOPIC__FAILURE when deleting existing topic', async () => {
  32. fetchMock.deleteOnce(
  33. `/api/clusters/${clusterName}/topics/${topicName}`,
  34. 404
  35. );
  36. try {
  37. await store.dispatch(thunks.deleteTopic(clusterName, topicName));
  38. } catch (error) {
  39. const err = error as Response;
  40. expect(err.status).toEqual(404);
  41. expect(store.getActions()).toEqual([
  42. actions.deleteTopicAction.request(),
  43. actions.deleteTopicAction.failure(),
  44. ]);
  45. }
  46. });
  47. });
  48. describe('recreateTopic', () => {
  49. it('creates RECREATE_TOPIC__SUCCESS when recreating existing topic', async () => {
  50. fetchMock.postOnce(
  51. `/api/clusters/${clusterName}/topics/${topicName}`,
  52. internalTopicPayload
  53. );
  54. await store.dispatch(thunks.recreateTopic(clusterName, topicName));
  55. expect(getTypeAndPayload(store)).toEqual([
  56. actions.recreateTopicAction.request(),
  57. actions.recreateTopicAction.success(internalTopicPayload),
  58. ...getAlertActions(store),
  59. ]);
  60. });
  61. it('creates RECREATE_TOPIC__FAILURE when recreating existing topic', async () => {
  62. fetchMock.postOnce(
  63. `/api/clusters/${clusterName}/topics/${topicName}`,
  64. 404
  65. );
  66. try {
  67. await store.dispatch(thunks.recreateTopic(clusterName, topicName));
  68. } catch (error) {
  69. const err = error as Response;
  70. expect(err.status).toEqual(404);
  71. expect(store.getActions()).toEqual([
  72. actions.recreateTopicAction.request(),
  73. actions.recreateTopicAction.failure(),
  74. ]);
  75. }
  76. });
  77. });
  78. describe('fetchTopicConsumerGroups', () => {
  79. it('GET_TOPIC_CONSUMER_GROUPS__FAILURE', async () => {
  80. fetchMock.getOnce(
  81. `api/clusters/${clusterName}/topics/${topicName}/consumer-groups`,
  82. 404
  83. );
  84. try {
  85. await store.dispatch(
  86. thunks.fetchTopicConsumerGroups(clusterName, topicName)
  87. );
  88. } catch (error) {
  89. const err = error as Response;
  90. expect(err.status).toEqual(404);
  91. expect(store.getActions()).toEqual([
  92. actions.fetchTopicConsumerGroupsAction.request(),
  93. actions.fetchTopicConsumerGroupsAction.failure(),
  94. ]);
  95. }
  96. });
  97. it('GET_TOPIC_CONSUMER_GROUPS__SUCCESS', async () => {
  98. fetchMock.getOnce(
  99. `api/clusters/${clusterName}/topics/${topicName}/consumer-groups`,
  100. 200
  101. );
  102. try {
  103. await store.dispatch(
  104. thunks.fetchTopicConsumerGroups(clusterName, topicName)
  105. );
  106. } catch (error) {
  107. const err = error as Response;
  108. expect(err.status).toEqual(200);
  109. expect(store.getActions()).toEqual([
  110. actions.fetchTopicConsumerGroupsAction.request(),
  111. actions.fetchTopicConsumerGroupsAction.success(mockTopicsState),
  112. ]);
  113. }
  114. });
  115. });
  116. describe('fetchTopicMessageSchema', () => {
  117. it('creates GET_TOPIC_SCHEMA__FAILURE', async () => {
  118. fetchMock.getOnce(
  119. `/api/clusters/${clusterName}/topics/${topicName}/messages/schema`,
  120. 404
  121. );
  122. try {
  123. await store.dispatch(
  124. thunks.fetchTopicMessageSchema(clusterName, topicName)
  125. );
  126. } catch (error) {
  127. const err = error as Response;
  128. expect(err.status).toEqual(404);
  129. expect(store.getActions()).toEqual([
  130. actions.fetchTopicMessageSchemaAction.request(),
  131. actions.fetchTopicMessageSchemaAction.failure({
  132. alert: {
  133. subject: ['topic', topicName].join('-'),
  134. title: `Topic Schema ${topicName}`,
  135. response: err,
  136. },
  137. }),
  138. ]);
  139. }
  140. });
  141. it('creates GET_TOPIC_SCHEMA__SUCCESS', async () => {
  142. const messageSchema: TopicMessageSchema = {
  143. key: {
  144. name: 'key',
  145. source: MessageSchemaSourceEnum.SCHEMA_REGISTRY,
  146. schema: `{
  147. "$schema": "http://json-schema.org/draft-07/schema#",
  148. "$id": "http://example.com/myURI.schema.json",
  149. "title": "TestRecord",
  150. "type": "object",
  151. "additionalProperties": false,
  152. "properties": {
  153. "f1": {
  154. "type": "integer"
  155. },
  156. "f2": {
  157. "type": "string"
  158. },
  159. "schema": {
  160. "type": "string"
  161. }
  162. }
  163. }
  164. `,
  165. },
  166. value: {
  167. name: 'value',
  168. source: MessageSchemaSourceEnum.SCHEMA_REGISTRY,
  169. schema: `{
  170. "$schema": "http://json-schema.org/draft-07/schema#",
  171. "$id": "http://example.com/myURI1.schema.json",
  172. "title": "TestRecord",
  173. "type": "object",
  174. "additionalProperties": false,
  175. "properties": {
  176. "f1": {
  177. "type": "integer"
  178. },
  179. "f2": {
  180. "type": "string"
  181. },
  182. "schema": {
  183. "type": "string"
  184. }
  185. }
  186. }
  187. `,
  188. },
  189. };
  190. fetchMock.getOnce(
  191. `/api/clusters/${clusterName}/topics/${topicName}/messages/schema`,
  192. messageSchema
  193. );
  194. await store.dispatch(
  195. thunks.fetchTopicMessageSchema(clusterName, topicName)
  196. );
  197. expect(store.getActions()).toEqual([
  198. actions.fetchTopicMessageSchemaAction.request(),
  199. actions.fetchTopicMessageSchemaAction.success({
  200. topicName,
  201. schema: messageSchema,
  202. }),
  203. ]);
  204. });
  205. });
  206. describe('increasing partitions count', () => {
  207. it('calls updateTopicPartitionsCountAction.success on success', async () => {
  208. fetchMock.patchOnce(
  209. `/api/clusters/${clusterName}/topics/${topicName}/partitions`,
  210. { totalPartitionsCount: 4, topicName }
  211. );
  212. await store.dispatch(
  213. thunks.updateTopicPartitionsCount(clusterName, topicName, 4)
  214. );
  215. expect(store.getActions()).toEqual([
  216. actions.updateTopicPartitionsCountAction.request(),
  217. actions.updateTopicPartitionsCountAction.success(),
  218. ]);
  219. });
  220. it('calls updateTopicPartitionsCountAction.failure on failure', async () => {
  221. fetchMock.patchOnce(
  222. `/api/clusters/${clusterName}/topics/${topicName}/partitions`,
  223. 404
  224. );
  225. try {
  226. await store.dispatch(
  227. thunks.updateTopicPartitionsCount(clusterName, topicName, 4)
  228. );
  229. } catch (error) {
  230. const response = await getResponse(error as Response);
  231. const alert: FailurePayload = {
  232. subject: ['topic-partitions', topicName].join('-'),
  233. title: `Topic ${topicName} partitions count increase failed`,
  234. response,
  235. };
  236. expect(store.getActions()).toEqual([
  237. actions.updateTopicPartitionsCountAction.request(),
  238. actions.updateTopicPartitionsCountAction.failure({ alert }),
  239. ]);
  240. }
  241. });
  242. });
  243. describe('updating replication factor', () => {
  244. it('calls updateTopicReplicationFactorAction.success on success', async () => {
  245. fetchMock.patchOnce(
  246. `/api/clusters/${clusterName}/topics/${topicName}/replications`,
  247. { totalReplicationFactor: 4, topicName }
  248. );
  249. await store.dispatch(
  250. thunks.updateTopicReplicationFactor(clusterName, topicName, 4)
  251. );
  252. expect(store.getActions()).toEqual([
  253. actions.updateTopicReplicationFactorAction.request(),
  254. actions.updateTopicReplicationFactorAction.success(),
  255. ]);
  256. });
  257. it('calls updateTopicReplicationFactorAction.failure on failure', async () => {
  258. fetchMock.patchOnce(
  259. `/api/clusters/${clusterName}/topics/${topicName}/replications`,
  260. 404
  261. );
  262. try {
  263. await store.dispatch(
  264. thunks.updateTopicReplicationFactor(clusterName, topicName, 4)
  265. );
  266. } catch (error) {
  267. const err = error as Response;
  268. const response = await getResponse(err);
  269. const alert: FailurePayload = {
  270. subject: ['topic-replication-factor', topicName].join('-'),
  271. title: `Topic ${topicName} replication factor change failed`,
  272. response,
  273. };
  274. expect(store.getActions()).toEqual([
  275. actions.updateTopicReplicationFactorAction.request(),
  276. actions.updateTopicReplicationFactorAction.failure({ alert }),
  277. ]);
  278. }
  279. });
  280. });
  281. });