Repository: strapi/strapi
File: packages/core/admin/server/src/services/__tests__/encryption.test.ts (TypeScript)

Code before:

describe('Encryption Service', () => {
  const ENCRYPTION_KEY = crypto.randomBytes(32).toString('hex');

  beforeEach(() => {
    global.strapi = {
      config: {
        get: jest.fn((key) => {
          if (key === 'admin.secrets.encryptionKey') {
            return ENCRYPTION_KEY;
          }
          return undefined;
        }),
      },
      log: {
        warn: jest.fn(),
      },
    } as any;
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('encrypt', () => {
    test('encrypts and returns a colon-separated string', () => {
      const encrypted = encryption.encrypt('super secret');
      expect(encrypted).toMatch(/^[a-f0-9]+:[a-f0-9]+:[a-f0-9]+$/);
      expect(encrypted!.split(':')).toHaveLength(3);
    });

    test('returns null and logs warning when key is missing', () => {
      (global.strapi.config.get as jest.Mock).mockReturnValue(undefined);
      const result = encryption.encrypt('test');
      expect(result).toBeNull();
      expect(global.strapi.log.warn).toHaveBeenCalledWith('Encryption key is missing from config');
    });
  });

  describe('decrypt', () => {
    test('round-trips encrypted → decrypted', () => {
      const original = 'secret message';
      const encrypted = encryption.encrypt(original);
      const decrypted = encryption.decrypt(encrypted!);
      expect(decrypted).toBe(original);
    });

    test('throws for malformed input', () => {
      expect(() => encryption.decrypt('bad-format')).toThrow('Invalid encrypted value format');
    });


Review comment (security):

```suggestion
    test('encrypts and returns a three-part colon-separated string (iv, auth, enrypted)'), () => {
```
just because I was confused why we had this test 😆

Code after:

describe('Encryption Service', () => {
  const ENCRYPTION_KEY = crypto.randomBytes(32).toString('hex');

  beforeEach(() => {
    global.strapi = {
      config: {
        get: jest.fn((key) => {
          if (key === 'admin.secrets.encryptionKey') {
            return ENCRYPTION_KEY;
          }
          return undefined;
        }),
      },
      log: {
        warn: jest.fn(),
      },
    } as any;
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('encrypt', () => {
    test('encrypts and returns a four-part colon-separated string (version, iv, encrypted, auth)', () => {
      const encrypted = encryption.encrypt('super secret');

      expect(encrypted).toMatch(/^v1:[a-f0-9]+:[a-f0-9]+:[a-f0-9]+$/);

      const parts = encrypted!.split(':');
      expect(parts).toHaveLength(4);
    });

    test('returns null and logs warning when key is missing', () => {
      (global.strapi.config.get as jest.Mock).mockReturnValue(undefined);
      const result = encryption.encrypt('test');
      expect(result).toBeNull();
      expect(global.strapi.log.warn).toHaveBeenCalledWith('Encryption key is missing from config');
    });
  });

  describe('decrypt', () => {
    test('round-trips encrypted → decrypted', () => {
      const original = 'secret message';
      const encrypted = encryption.encrypt(original);
      const decrypted = encryption.decrypt(encrypted!);
      expect(decrypted).toBe(original);
    });

    test('throws for malformed input', () => {