system.service.test.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. import fs from 'fs-extra';
  2. import semver from 'semver';
  3. import axios from 'axios';
  4. import { faker } from '@faker-js/faker';
  5. import SystemService from '../system.service';
  6. import TipiCache from '../../../config/TipiCache';
  7. import { setConfig } from '../../../core/config/TipiConfig';
  8. import logger from '../../../config/logger/logger';
  9. import EventDispatcher from '../../../core/config/EventDispatcher';
  10. jest.mock('fs-extra');
  11. jest.mock('axios');
  12. jest.mock('redis');
  13. beforeEach(async () => {
  14. jest.resetModules();
  15. jest.resetAllMocks();
  16. });
  17. describe('Test: systemInfo', () => {
  18. it('Should throw if system-info.json does not exist', () => {
  19. try {
  20. SystemService.systemInfo();
  21. } catch (e: any) {
  22. expect(e).toBeDefined();
  23. expect(e.message).toBe('Error parsing system info');
  24. }
  25. });
  26. it('It should return system info', async () => {
  27. // Arrange
  28. const info = {
  29. cpu: { load: 0.1 },
  30. memory: { available: 1000, total: 2000, used: 1000 },
  31. disk: { available: 1000, total: 2000, used: 1000 },
  32. };
  33. const MockFiles = {
  34. '/runtipi/state/system-info.json': JSON.stringify(info),
  35. };
  36. // @ts-ignore
  37. fs.__createMockFiles(MockFiles);
  38. // Act
  39. const systemInfo = SystemService.systemInfo();
  40. // Assert
  41. expect(systemInfo).toBeDefined();
  42. expect(systemInfo.cpu).toBeDefined();
  43. expect(systemInfo.memory).toBeDefined();
  44. });
  45. });
  46. describe('Test: getVersion', () => {
  47. beforeEach(() => {
  48. TipiCache.del('latestVersion');
  49. });
  50. afterAll(() => {
  51. jest.restoreAllMocks();
  52. });
  53. it('It should return version', async () => {
  54. // Arrange
  55. const spy = jest.spyOn(axios, 'get').mockResolvedValue({
  56. data: { name: `v${faker.random.numeric(1)}.${faker.random.numeric(1)}.${faker.random.numeric()}` },
  57. });
  58. // Act
  59. const version = await SystemService.getVersion();
  60. // Assert
  61. expect(version).toBeDefined();
  62. expect(version.current).toBeDefined();
  63. expect(semver.valid(version.latest)).toBeTruthy();
  64. spy.mockRestore();
  65. });
  66. it('Should return undefined for latest if request fails', async () => {
  67. jest.spyOn(axios, 'get').mockImplementation(() => {
  68. throw new Error('Error');
  69. });
  70. const version = await SystemService.getVersion();
  71. expect(version).toBeDefined();
  72. expect(version.current).toBeDefined();
  73. expect(version.latest).toBeUndefined();
  74. });
  75. it('Should return cached version', async () => {
  76. // Arrange
  77. const spy = jest.spyOn(axios, 'get').mockResolvedValue({
  78. data: { name: `v${faker.random.numeric(1)}.${faker.random.numeric(1)}.${faker.random.numeric()}` },
  79. });
  80. // Act
  81. const version = await SystemService.getVersion();
  82. const version2 = await SystemService.getVersion();
  83. // Assert
  84. expect(version).toBeDefined();
  85. expect(version.current).toBeDefined();
  86. expect(semver.valid(version.latest)).toBeTruthy();
  87. expect(version2.latest).toBe(version.latest);
  88. expect(version2.current).toBeDefined();
  89. expect(semver.valid(version2.latest)).toBeTruthy();
  90. expect(spy).toHaveBeenCalledTimes(1);
  91. spy.mockRestore();
  92. });
  93. });
  94. describe('Test: restart', () => {
  95. it('Should return true', async () => {
  96. // Arrange
  97. EventDispatcher.prototype.dispatchEventAsync = jest.fn().mockResolvedValueOnce({ success: true });
  98. // Act
  99. const restart = await SystemService.restart();
  100. // Assert
  101. expect(restart).toBeTruthy();
  102. });
  103. it('Should log error if fails', async () => {
  104. // Arrange
  105. EventDispatcher.prototype.dispatchEventAsync = jest.fn().mockResolvedValueOnce({ success: false, stdout: 'fake' });
  106. const log = jest.spyOn(logger, 'error');
  107. // Act
  108. const restart = await SystemService.restart();
  109. // Assert
  110. expect(restart).toBeFalsy();
  111. expect(log).toHaveBeenCalledWith('Error restarting system: fake');
  112. log.mockRestore();
  113. });
  114. });
  115. describe('Test: update', () => {
  116. it('Should return true', async () => {
  117. // Arrange
  118. EventDispatcher.prototype.dispatchEventAsync = jest.fn().mockResolvedValueOnce({ success: true });
  119. setConfig('version', '0.0.1');
  120. TipiCache.set('latestVersion', '0.0.2');
  121. // Act
  122. const update = await SystemService.update();
  123. // Assert
  124. expect(update).toBeTruthy();
  125. });
  126. it('Should throw an error if latest version is not set', async () => {
  127. // Arrange
  128. TipiCache.del('latestVersion');
  129. const spy = jest.spyOn(axios, 'get').mockResolvedValue({
  130. data: { name: null },
  131. });
  132. setConfig('version', '0.0.1');
  133. // Act & Assert
  134. await expect(SystemService.update()).rejects.toThrow('Could not get latest version');
  135. spy.mockRestore();
  136. });
  137. it('Should throw if current version is higher than latest', async () => {
  138. // Arrange
  139. setConfig('version', '0.0.2');
  140. TipiCache.set('latestVersion', '0.0.1');
  141. // Act & Assert
  142. await expect(SystemService.update()).rejects.toThrow('Current version is newer than latest version');
  143. });
  144. it('Should throw if current version is equal to latest', async () => {
  145. // Arrange
  146. setConfig('version', '0.0.1');
  147. TipiCache.set('latestVersion', '0.0.1');
  148. // Act & Assert
  149. await expect(SystemService.update()).rejects.toThrow('Current version is already up to date');
  150. });
  151. it('Should throw an error if there is a major version difference', async () => {
  152. // Arrange
  153. setConfig('version', '0.0.1');
  154. TipiCache.set('latestVersion', '1.0.0');
  155. // Act & Assert
  156. await expect(SystemService.update()).rejects.toThrow('The major version has changed. Please update manually');
  157. });
  158. it('Should log error if fails', async () => {
  159. // Arrange
  160. EventDispatcher.prototype.dispatchEventAsync = jest.fn().mockResolvedValueOnce({ success: false, stdout: 'fake2' });
  161. const log = jest.spyOn(logger, 'error');
  162. // Act
  163. setConfig('version', '0.0.1');
  164. TipiCache.set('latestVersion', '0.0.2');
  165. const update = await SystemService.update();
  166. // Assert
  167. expect(update).toBeFalsy();
  168. expect(log).toHaveBeenCalledWith('Error updating system: fake2');
  169. log.mockRestore();
  170. });
  171. });