PageRenderTime 26ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/spec/javascripts/lib/utils/poll_spec.js

https://gitlab.com/artofhuman/gitlab-ce
JavaScript | 190 lines | 151 code | 38 blank | 1 comment | 4 complexity | fa1475ba9b257e8bb50d7f38e8049237 MD5 | raw file
  1. /* eslint-disable jasmine/no-unsafe-spy */
  2. import Poll from '~/lib/utils/poll';
  3. import { successCodes } from '~/lib/utils/http_status';
  4. const waitForAllCallsToFinish = (service, waitForCount, successCallback) => {
  5. const timer = () => {
  6. setTimeout(() => {
  7. if (service.fetch.calls.count() === waitForCount) {
  8. successCallback();
  9. } else {
  10. timer();
  11. }
  12. }, 0);
  13. };
  14. timer();
  15. };
  16. function mockServiceCall(service, response, shouldFail = false) {
  17. const action = shouldFail ? Promise.reject : Promise.resolve;
  18. const responseObject = response;
  19. if (!responseObject.headers) responseObject.headers = {};
  20. service.fetch.and.callFake(action.bind(Promise, responseObject));
  21. }
  22. describe('Poll', () => {
  23. const service = jasmine.createSpyObj('service', ['fetch']);
  24. const callbacks = jasmine.createSpyObj('callbacks', ['success', 'error', 'notification']);
  25. function setup() {
  26. return new Poll({
  27. resource: service,
  28. method: 'fetch',
  29. successCallback: callbacks.success,
  30. errorCallback: callbacks.error,
  31. notificationCallback: callbacks.notification,
  32. }).makeRequest();
  33. }
  34. afterEach(() => {
  35. callbacks.success.calls.reset();
  36. callbacks.error.calls.reset();
  37. callbacks.notification.calls.reset();
  38. service.fetch.calls.reset();
  39. });
  40. it('calls the success callback when no header for interval is provided', done => {
  41. mockServiceCall(service, { status: 200 });
  42. setup();
  43. waitForAllCallsToFinish(service, 1, () => {
  44. expect(callbacks.success).toHaveBeenCalled();
  45. expect(callbacks.error).not.toHaveBeenCalled();
  46. done();
  47. });
  48. });
  49. it('calls the error callback when the http request returns an error', done => {
  50. mockServiceCall(service, { status: 500 }, true);
  51. setup();
  52. waitForAllCallsToFinish(service, 1, () => {
  53. expect(callbacks.success).not.toHaveBeenCalled();
  54. expect(callbacks.error).toHaveBeenCalled();
  55. done();
  56. });
  57. });
  58. it('skips the error callback when request is aborted', done => {
  59. mockServiceCall(service, { status: 0 }, true);
  60. setup();
  61. waitForAllCallsToFinish(service, 1, () => {
  62. expect(callbacks.success).not.toHaveBeenCalled();
  63. expect(callbacks.error).not.toHaveBeenCalled();
  64. expect(callbacks.notification).toHaveBeenCalled();
  65. done();
  66. });
  67. });
  68. it('should call the success callback when the interval header is -1', done => {
  69. mockServiceCall(service, { status: 200, headers: { 'poll-interval': -1 } });
  70. setup()
  71. .then(() => {
  72. expect(callbacks.success).toHaveBeenCalled();
  73. expect(callbacks.error).not.toHaveBeenCalled();
  74. done();
  75. })
  76. .catch(done.fail);
  77. });
  78. describe('for 2xx status code', () => {
  79. successCodes.forEach(httpCode => {
  80. it(`starts polling when http status is ${httpCode} and interval header is provided`, done => {
  81. mockServiceCall(service, { status: httpCode, headers: { 'poll-interval': 1 } });
  82. const Polling = new Poll({
  83. resource: service,
  84. method: 'fetch',
  85. data: { page: 1 },
  86. successCallback: callbacks.success,
  87. errorCallback: callbacks.error,
  88. });
  89. Polling.makeRequest();
  90. waitForAllCallsToFinish(service, 2, () => {
  91. Polling.stop();
  92. expect(service.fetch.calls.count()).toEqual(2);
  93. expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
  94. expect(callbacks.success).toHaveBeenCalled();
  95. expect(callbacks.error).not.toHaveBeenCalled();
  96. done();
  97. });
  98. });
  99. });
  100. });
  101. describe('stop', () => {
  102. it('stops polling when method is called', done => {
  103. mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } });
  104. const Polling = new Poll({
  105. resource: service,
  106. method: 'fetch',
  107. data: { page: 1 },
  108. successCallback: () => {
  109. Polling.stop();
  110. },
  111. errorCallback: callbacks.error,
  112. });
  113. spyOn(Polling, 'stop').and.callThrough();
  114. Polling.makeRequest();
  115. waitForAllCallsToFinish(service, 1, () => {
  116. expect(service.fetch.calls.count()).toEqual(1);
  117. expect(service.fetch).toHaveBeenCalledWith({ page: 1 });
  118. expect(Polling.stop).toHaveBeenCalled();
  119. done();
  120. });
  121. });
  122. });
  123. describe('restart', () => {
  124. it('should restart polling when its called', done => {
  125. mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } });
  126. const Polling = new Poll({
  127. resource: service,
  128. method: 'fetch',
  129. data: { page: 1 },
  130. successCallback: () => {
  131. Polling.stop();
  132. setTimeout(() => {
  133. Polling.restart({ data: { page: 4 } });
  134. }, 0);
  135. },
  136. errorCallback: callbacks.error,
  137. });
  138. spyOn(Polling, 'stop').and.callThrough();
  139. spyOn(Polling, 'restart').and.callThrough();
  140. Polling.makeRequest();
  141. waitForAllCallsToFinish(service, 2, () => {
  142. Polling.stop();
  143. expect(service.fetch.calls.count()).toEqual(2);
  144. expect(service.fetch).toHaveBeenCalledWith({ page: 4 });
  145. expect(Polling.stop).toHaveBeenCalled();
  146. expect(Polling.restart).toHaveBeenCalled();
  147. expect(Polling.options.data).toEqual({ page: 4 });
  148. done();
  149. });
  150. });
  151. });
  152. });