Skip to content
Snippets Groups Projects
Select Git revision
  • bf629189a99b98ddc19cedda19f3a3c093789d78
  • main default protected
  • 3-rewrite-in-typescript
  • 1.13.6
  • 1.13.5
  • 1.13.4
  • 1.13.3
  • 1.13.2
  • 1.13.1
  • 1.13.0
  • 1.12.4
  • 1.12.3
  • 1.12.2
  • 1.12.1
  • 1.12.0
  • 1.11.0
  • 1.10.1
  • 1.10.0
  • 1.9.0
  • v1.7.0
  • 1.8.0
  • v1.7.1
  • v1.6.2
23 results

index.test.ts

Blame
  • index.test.ts 10.73 KiB
    import { promises as fs } from 'fs';
    import { createConfig } from './index';
    
    // Test JSON data
    const jsonDefaults = {
      setting: 'defaultvalue',
      another: {
        setting: 'avalue',
      },
    };
    
    const jsonLocals = {
      setting: 'localvalue',
      another: {
        more: 'stuff',
      },
      even: {
        deeper: {
          key: 'sodeep',
        },
      },
    };
    
    describe('Config', () => {
      it('should only have values from config.defaults.json', async () => {
        await fs.writeFile('config.defaults.json', JSON.stringify(jsonDefaults));
        const config = createConfig();
        await fs.unlink('config.defaults.json');
    
        expect(config.setting).toBe('defaultvalue');
        expect(config.another.setting).toBe('avalue');
      });
    
      it('should only have values from config.json', async () => {
        await fs.writeFile('config.json', JSON.stringify(jsonLocals));
        const config = createConfig();
        await fs.unlink('config.json');
    
        expect(config.setting).toBe('localvalue');
        expect(config.another.more).toBe('stuff');
      });
    
      it('should have both values with preference to config.json', async () => {
        await fs.writeFile('config.defaults.json', JSON.stringify(jsonDefaults));
        await fs.writeFile('config.json', JSON.stringify(jsonLocals));
        const config = createConfig();
        await fs.unlink('config.json');
        await fs.unlink('config.defaults.json');
    
        expect(config.setting).toBe('localvalue');
        expect(config.another.more).toBe('stuff');
        expect(config.another.setting).toBe('avalue');
      });
    
      it('should respect a given basePath', async () => {
        // Create the tmp directory only if it doesn't exist
        await fs.mkdir('tmp', { recursive: true });
        
        await fs.writeFile('tmp/config.defaults.json', JSON.stringify(jsonDefaults));
        await fs.writeFile('tmp/config.json', JSON.stringify(jsonLocals));
        
        const config = createConfig('tmp');
        
        await fs.unlink('tmp/config.json');
        await fs.unlink('tmp/config.defaults.json');
        
        // Remove the tmp directory after the test
        await fs.rmdir('tmp', { recursive: true });
      
        expect(config.setting).toBe('localvalue');
        expect(config.another.more).toBe('stuff');
        expect(config.another.setting).toBe('avalue');
      });
    
      it('should have all values with preference to env', async () => {
        await fs.writeFile('config.defaults.json', JSON.stringify(jsonDefaults));
        await fs.writeFile('config.json', JSON.stringify(jsonLocals));
    
        process.env['SETTING'] = 'overwritten-by-env';
        process.env['ANOTHER_MORE'] = 'false';
        process.env['EVEN_DEEPER_KEY'] = 'true';
    
        const config = createConfig();
    
        await fs.unlink('config.json');
        await fs.unlink('config.defaults.json');
    
        delete process.env['SETTING'];
        delete process.env['ANOTHER_MORE'];
        delete process.env['EVEN_DEEPER_KEY'];
    
        expect(config.setting).toBe('overwritten-by-env');
        expect(config.another.more).toBe(false);
        expect(config.even.deeper.key).toBe(true);
        expect(config.another.setting).toBe('avalue');
      });
    
      it('should have all values with preference to env and prefix', async () => {
        await fs.writeFile('config.defaults.json', JSON.stringify(jsonDefaults));
        await fs.writeFile('config.json', JSON.stringify(jsonLocals));
    
        process.env['P_SETTING'] = 'overwritten-by-env';
        process.env['P_ANOTHER_MORE'] = 'false';
        process.env['P_EVEN_DEEPER_KEY'] = 'true';
    
        const config = createConfig(undefined, 'p');
    
        await fs.unlink('config.json');
        await fs.unlink('config.defaults.json');
    
        delete process.env['P_SETTING'];
        delete process.env['P_ANOTHER_MORE'];
        delete process.env['P_EVEN_DEEPER_KEY'];
    
        expect(config.setting).toBe('overwritten-by-env');
        expect(config.another.more).toBe(false);
        expect(config.even.deeper.key).toBe(true);
        expect(config.another.setting).toBe('avalue');
      });
    
      it('should read in a file when given', async () => {
        jsonLocals.setting = 'file:file.txt';
        await fs.writeFile('config.defaults.json', JSON.stringify(jsonDefaults));
        await fs.writeFile('config.json', JSON.stringify(jsonLocals));
        await fs.writeFile('file.txt', 'value-from-file');
    
        const config = createConfig();
    
        await fs.unlink('config.json');
        await fs.unlink('config.defaults.json');
        await fs.unlink('file.txt');
        jsonLocals.setting = 'localvalue';
    
        expect(config.setting).toBe('value-from-file');
      });
    
      it('should show a message and keep the setting when file given but not found', async () => {
        jsonLocals.setting = 'file:file.txt';
        await fs.writeFile('config.defaults.json', JSON.stringify(jsonDefaults));
        await fs.writeFile('config.json', JSON.stringify(jsonLocals));
    
        const config = createConfig();
    
        await fs.unlink('config.json');
        await fs.unlink('config.defaults.json');
        jsonLocals.setting = 'localvalue';
    
        expect(config.setting).toBe('file:file.txt');
      });
    
      it('should _reload if asked', async () => {
        await fs.writeFile('config.defaults.json', JSON.stringify(jsonDefaults));
        await fs.writeFile('config.json', JSON.stringify(jsonLocals));
    
        const config = createConfig();
    
        expect(config.setting).toBe('localvalue');
    
        jsonLocals.setting = 'reloaded-value';
        await fs.writeFile('config.json', JSON.stringify(jsonLocals));
    
        config._reload();
    
        await fs.unlink('config.json');
        await fs.unlink('config.defaults.json');
        jsonLocals.setting = 'localvalue';
    
        expect(config.setting).toBe('reloaded-value');
      });
    
      it('should redact passwords if using _show', async () => {
        jsonLocals.even.deeper.key = 'password123';
        await fs.writeFile('config.defaults.json', JSON.stringify(jsonDefaults));
        await fs.writeFile('config.json', JSON.stringify(jsonLocals));
    
        const config = createConfig();
    
        await fs.unlink('config.json');
        await fs.unlink('config.defaults.json');
        jsonLocals.even.deeper.key = 'sodeep';
    
        expect(config._show().even.deeper.key).toBe('REDACTED');
      });
    
      it('should handle missing config.defaults.json gracefully', async () => {
        // Ensure config.defaults.json does not exist
        await fs.unlink('config.defaults.json').catch(() => {}); // Ignore errors if the file doesn't exist
      
        const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
      
        const config = createConfig();
      
        // Ensure no crash and empty config
        expect(config.setting).toBeUndefined();
      
        // Check if the missing file message was logged
        expect(consoleSpy).toHaveBeenCalledWith(
          expect.stringContaining(`Defaults file missing`)
        );
      
        consoleSpy.mockRestore();
      });
    
      it('should handle missing config.json gracefully', async () => {
        // Create config.defaults.json but ensure config.json does not exist
        await fs.writeFile('config.defaults.json', JSON.stringify(jsonDefaults));
        await fs.unlink('config.json').catch(() => {});
      
        const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
      
        const config = createConfig();
        await fs.unlink('config.defaults.json');
      
        // Expect log message for the missing file
        expect(consoleSpy).toHaveBeenCalledWith(
          expect.stringContaining('local file missing')
        );
      
        // Defaults should still be loaded
        expect(config.setting).toBe('defaultvalue');
        expect(config.another.setting).toBe('avalue');
    
        consoleSpy.mockRestore();
      });
    
      it('should handle invalid JSON content in config.defaults.json gracefully', async () => {
        // Write invalid JSON to config.defaults.json
        await fs.writeFile('config.defaults.json', '{ invalid json }');
        await fs.writeFile('config.json', JSON.stringify(jsonLocals));
    
        const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
      
        const config = createConfig();
    
        // Expect a log message for invalid JSON
        expect(consoleSpy).toHaveBeenCalledWith(
          expect.stringContaining('Error reading defaults file')
        );
      
        // Clean up files
        await fs.unlink('config.defaults.json');
        await fs.unlink('config.json');
      
      
        // Expect config.json to still load successfully
        expect(config.setting).toBe('localvalue');
        expect(config.another.more).toBe('stuff');
    
        consoleSpy.mockRestore();
      });
    
      it('should handle invalid JSON content in config.json gracefully', async () => {
        // Write invalid JSON to config.json
        await fs.writeFile('config.defaults.json', JSON.stringify(jsonDefaults));
        await fs.writeFile('config.json', '{ invalid json }');
    
        const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
      
        const config = createConfig();
    
        // Expect a log message for invalid JSON
        expect(consoleSpy).toHaveBeenCalledWith(
          expect.stringContaining('Error reading local config file')
        );
      
        // Clean up files
        await fs.unlink('config.defaults.json');
        await fs.unlink('config.json');
      
        // Expect defaults to still load successfully
        expect(config.setting).toBe('defaultvalue');
        expect(config.another.setting).toBe('avalue');
    
        consoleSpy.mockRestore();
      });
    
      it('should serialize only configData using toJSON()', async () => {
        // Create test configuration files
        await fs.writeFile('config.defaults.json', JSON.stringify(jsonDefaults));
        await fs.writeFile('config.json', JSON.stringify(jsonLocals));
      
        const config = createConfig();
      
        // Serialize the config object to JSON
        const serializedConfig = JSON.stringify(config);
      
        // Clean up test files
        await fs.unlink('config.defaults.json');
        await fs.unlink('config.json');
      
        // Parse the serialized JSON
        const parsedConfig = JSON.parse(serializedConfig);
      
        // Check that all expected configData properties are present
        expect(parsedConfig.setting).toBe('localvalue');
        expect(parsedConfig.another.setting).toBe('avalue'); // From defaults
        expect(parsedConfig.another.more).toBe('stuff'); // From local
        expect(parsedConfig.even.deeper.key).toBe('sodeep'); // From local
      
        // Ensure internal properties are not present
        expect(parsedConfig).not.toHaveProperty('configDefaults');
        expect(parsedConfig).not.toHaveProperty('configLocal');
        expect(parsedConfig).not.toHaveProperty('envPrefix');
      });
    
      it('should log an error if a file referenced by "file:" is missing', async () => {
        // Write test configuration file
        await fs.writeFile(
          'config.json',
          JSON.stringify({
            setting: 'file:nonexistent-file.txt',
          })
        );
      
        // Spy on console.error
        const consoleSpy = jest.spyOn(console, 'error').mockImplementation();
      
        const config = createConfig();
      
        // Clean up test files
        await fs.unlink('config.json');
      
        // Ensure the original "file:" reference remains unchanged
        expect(config.setting).toBe('file:nonexistent-file.txt');
      
        // Ensure error is logged for the missing file
        expect(consoleSpy).toHaveBeenCalledWith(
          expect.stringContaining('An unknown error occurred')
        );
      
        consoleSpy.mockRestore();
      });
    
    });