EventDispatcher.test.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import fs from 'fs-extra';
  2. import { EventDispatcher } from '.';
  3. const WATCH_FILE = '/runtipi/state/events';
  4. jest.mock('fs-extra');
  5. // eslint-disable-next-line no-promise-executor-return
  6. const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
  7. beforeEach(() => {
  8. EventDispatcher.clear();
  9. fs.writeFileSync(WATCH_FILE, '');
  10. fs.writeFileSync('/app/logs/123.log', 'test');
  11. });
  12. describe('EventDispatcher - dispatchEvent', () => {
  13. it('should dispatch an event', () => {
  14. const event = EventDispatcher.dispatchEvent('app');
  15. expect(event.id).toBeDefined();
  16. });
  17. it('should dispatch an event with args', () => {
  18. const event = EventDispatcher.dispatchEvent('app', ['--help']);
  19. expect(event.id).toBeDefined();
  20. });
  21. it('Should put events into queue', async () => {
  22. EventDispatcher.dispatchEvent('app', ['--help']);
  23. EventDispatcher.dispatchEvent('app', ['--help']);
  24. // @ts-expect-error - private method
  25. const { queue } = EventDispatcher;
  26. expect(queue.length).toBe(2);
  27. });
  28. it('Should put first event into lock after 1 sec', async () => {
  29. EventDispatcher.dispatchEvent('app', ['--help']);
  30. EventDispatcher.dispatchEvent('update', ['--help']);
  31. // @ts-expect-error - private method
  32. const { queue } = EventDispatcher;
  33. await wait(1050);
  34. // @ts-expect-error - private method
  35. const { lock } = EventDispatcher;
  36. expect(queue.length).toBe(2);
  37. expect(lock).toBeDefined();
  38. expect(lock?.type).toBe('app');
  39. });
  40. it('Should clear event once its status is success', async () => {
  41. // @ts-expect-error - private method
  42. jest.spyOn(EventDispatcher, 'getEventStatus').mockReturnValueOnce('success');
  43. EventDispatcher.dispatchEvent('app', ['--help']);
  44. await wait(1050);
  45. // @ts-expect-error - private method
  46. const { queue } = EventDispatcher;
  47. expect(queue.length).toBe(0);
  48. });
  49. it('Should clear event once its status is error', async () => {
  50. // @ts-expect-error - private method
  51. jest.spyOn(EventDispatcher, 'getEventStatus').mockReturnValueOnce('error');
  52. EventDispatcher.dispatchEvent('app', ['--help']);
  53. await wait(1050);
  54. // @ts-expect-error - private method
  55. const { queue } = EventDispatcher;
  56. expect(queue.length).toBe(0);
  57. });
  58. });
  59. describe('EventDispatcher - dispatchEventAsync', () => {
  60. it('Should dispatch an event and wait for it to finish', async () => {
  61. // @ts-expect-error - private method
  62. jest.spyOn(EventDispatcher, 'getEventStatus').mockReturnValueOnce('success');
  63. const { success } = await EventDispatcher.dispatchEventAsync('app', ['--help']);
  64. expect(success).toBe(true);
  65. });
  66. it('Should dispatch an event and wait for it to finish with error', async () => {
  67. // @ts-expect-error - private method
  68. jest.spyOn(EventDispatcher, 'getEventStatus').mockReturnValueOnce('error');
  69. const { success } = await EventDispatcher.dispatchEventAsync('app', ['--help']);
  70. expect(success).toBe(false);
  71. });
  72. });
  73. describe('EventDispatcher - runEvent', () => {
  74. it('Should do nothing if there is a lock', async () => {
  75. // @ts-expect-error - private method
  76. EventDispatcher.lock = { id: '123', type: 'app', args: [] };
  77. // @ts-expect-error - private method
  78. await EventDispatcher.runEvent();
  79. const file = fs.readFileSync(WATCH_FILE, 'utf8');
  80. expect(file).toBe('');
  81. });
  82. it('Should do nothing if there is no event in queue', async () => {
  83. // @ts-expect-error - private method
  84. await EventDispatcher.runEvent();
  85. const file = fs.readFileSync(WATCH_FILE, 'utf8');
  86. expect(file).toBe('');
  87. });
  88. });
  89. describe('EventDispatcher - getEventStatus', () => {
  90. it('Should return success if event is not in the queue', async () => {
  91. // @ts-expect-error - private method
  92. EventDispatcher.queue = [];
  93. // @ts-expect-error - private method
  94. const status = EventDispatcher.getEventStatus('123');
  95. expect(status).toBe('success');
  96. });
  97. it('Should return error if event is expired', async () => {
  98. const dateFiveMinutesAgo = new Date(new Date().getTime() - 5 * 60 * 10000);
  99. // @ts-expect-error - private method
  100. EventDispatcher.queue = [{ id: '123', type: 'app', args: [], creationDate: dateFiveMinutesAgo }];
  101. // @ts-expect-error - private method
  102. const status = EventDispatcher.getEventStatus('123');
  103. expect(status).toBe('error');
  104. });
  105. it('Should be waiting if line is not found in the file', async () => {
  106. // @ts-expect-error - private method
  107. EventDispatcher.queue = [{ id: '123', type: 'app', args: [], creationDate: new Date() }];
  108. // @ts-expect-error - private method
  109. const status = EventDispatcher.getEventStatus('123');
  110. expect(status).toBe('waiting');
  111. });
  112. });
  113. describe('EventDispatcher - clearEvent', () => {
  114. it('Should clear event', async () => {
  115. const event = { id: '123', type: 'app', args: [], creationDate: new Date() };
  116. // @ts-expect-error - private method
  117. EventDispatcher.queue = [event];
  118. // @ts-expect-error - private method
  119. EventDispatcher.clearEvent(event);
  120. // @ts-expect-error - private method
  121. const { queue } = EventDispatcher;
  122. expect(queue.length).toBe(0);
  123. });
  124. });
  125. describe('EventDispatcher - pollQueue', () => {
  126. it('Should not create a new interval if one already exists', async () => {
  127. // @ts-expect-error - private method
  128. EventDispatcher.interval = 123;
  129. // @ts-expect-error - private method
  130. const id = EventDispatcher.pollQueue();
  131. // @ts-expect-error - private method
  132. const { interval } = EventDispatcher;
  133. expect(interval).toBe(123);
  134. expect(id).toBe(123);
  135. clearInterval(interval);
  136. clearInterval(id);
  137. });
  138. });
  139. describe('EventDispatcher - collectLockStatusAndClean', () => {
  140. it('Should do nothing if there is no lock', async () => {
  141. // @ts-expect-error - private method
  142. EventDispatcher.lock = null;
  143. // @ts-expect-error - private method
  144. EventDispatcher.collectLockStatusAndClean();
  145. // @ts-expect-error - private method
  146. const { lock } = EventDispatcher;
  147. expect(lock).toBeNull();
  148. });
  149. });