config.service.spec.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import { Test, TestingModule } from '@nestjs/testing';
  2. import Database from 'better-sqlite3';
  3. import path from 'path';
  4. import { ConfigService } from './config.service';
  5. // Mock better-sqlite3
  6. jest.mock('better-sqlite3', () => {
  7. const mockDb = {
  8. exec: jest.fn(),
  9. prepare: jest.fn().mockReturnValue({
  10. run: jest.fn().mockReturnValue({}),
  11. get: jest.fn(),
  12. all: jest.fn(),
  13. }),
  14. close: jest.fn(),
  15. };
  16. return jest.fn(() => mockDb);
  17. });
  18. describe('ConfigService', () => {
  19. let service: ConfigService;
  20. let mockDb: any;
  21. beforeEach(async () => {
  22. jest.clearAllMocks();
  23. const module: TestingModule = await Test.createTestingModule({
  24. providers: [ConfigService],
  25. }).compile();
  26. service = module.get<ConfigService>(ConfigService);
  27. mockDb = (Database as jest.MockedFunction<typeof Database>).mock.results[0]
  28. ?.value;
  29. });
  30. it('should be defined', () => {
  31. expect(service).toBeDefined();
  32. });
  33. describe('constructor', () => {
  34. it('should create database and table on initialization', () => {
  35. expect(Database).toHaveBeenCalledWith(
  36. path.resolve(__dirname, '../../../data', 'database.db'),
  37. );
  38. expect(mockDb.exec).toHaveBeenCalledWith(
  39. expect.stringContaining('CREATE TABLE IF NOT EXISTS settings'),
  40. );
  41. expect(mockDb.close).toHaveBeenCalled();
  42. });
  43. });
  44. describe('getSettings', () => {
  45. beforeEach(() => {
  46. // Reset the mock for each test
  47. mockDb.prepare.mockClear();
  48. mockDb.close.mockClear();
  49. });
  50. it('should return all settings when no key provided', () => {
  51. const mockAll = mockDb.prepare().all;
  52. mockAll.mockReturnValue([
  53. { key: 'testKey', value: JSON.stringify('testValue') },
  54. ]);
  55. const result = service.getSettings();
  56. expect(mockDb.prepare).toHaveBeenCalledWith(
  57. 'SELECT key, value FROM settings',
  58. );
  59. expect(result).toEqual({ testKey: 'testValue' });
  60. expect(mockDb.close).toHaveBeenCalled();
  61. });
  62. it('should return specific setting when key provided', () => {
  63. const mockGet = mockDb.prepare().get;
  64. mockGet.mockReturnValue({ value: JSON.stringify('testValue') });
  65. const result = service.getSettings('testKey');
  66. expect(mockDb.prepare).toHaveBeenCalledWith(
  67. 'SELECT value FROM settings WHERE key = ?',
  68. );
  69. expect(result).toEqual('testValue');
  70. expect(mockDb.close).toHaveBeenCalled();
  71. });
  72. it('should return default value when key not found', () => {
  73. const mockGet = mockDb.prepare().get;
  74. mockGet.mockReturnValue(undefined);
  75. const result = service.getSettings('missingKey', 'defaultValue');
  76. expect(result).toEqual('defaultValue');
  77. expect(mockDb.close).toHaveBeenCalled();
  78. });
  79. });
  80. describe('setSettings', () => {
  81. beforeEach(() => {
  82. mockDb.prepare.mockClear();
  83. mockDb.close.mockClear();
  84. });
  85. it('should insert settings successfully', () => {
  86. const settings = { key1: 'value1', key2: 'value2' };
  87. const result = service.setSettings(settings);
  88. expect(Database).toHaveBeenCalledTimes(2); // Constructor + setSettings
  89. expect(mockDb.prepare).toHaveBeenCalledWith(
  90. 'INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)',
  91. );
  92. const mockRun = mockDb.prepare().run;
  93. expect(mockRun).toHaveBeenCalledTimes(2);
  94. expect(mockRun).toHaveBeenCalledWith('key1', JSON.stringify('value1'));
  95. expect(mockRun).toHaveBeenCalledWith('key2', JSON.stringify('value2'));
  96. expect(mockDb.close).toHaveBeenCalled();
  97. expect(result).toBe(true);
  98. });
  99. it('should return false on database error', () => {
  100. const settings = { key1: 'value1' };
  101. const mockRun = mockDb.prepare().run;
  102. mockRun.mockImplementation(() => {
  103. throw new Error('Database error');
  104. });
  105. const result = service.setSettings(settings);
  106. expect(result).toBe(false);
  107. });
  108. });
  109. describe('deleteSetting', () => {
  110. beforeEach(() => {
  111. mockDb.prepare.mockClear();
  112. mockDb.close.mockClear();
  113. });
  114. it('should delete setting successfully', () => {
  115. const mockRun = mockDb.prepare().run;
  116. mockRun.mockReturnValue({ changes: 1 });
  117. const result = service.deleteSetting('testKey');
  118. expect(mockDb.prepare).toHaveBeenCalledWith(
  119. 'DELETE FROM settings WHERE key = ?',
  120. );
  121. expect(mockRun).toHaveBeenCalledWith('testKey');
  122. expect(mockDb.close).toHaveBeenCalled();
  123. expect(result).toBe(true);
  124. });
  125. it('should return false on database error', () => {
  126. const mockRun = mockDb.prepare().run;
  127. mockRun.mockImplementation(() => {
  128. throw new Error('Database error');
  129. });
  130. const result = service.deleteSetting('testKey');
  131. expect(result).toBe(false);
  132. });
  133. });
  134. });