Files
Containr/app/frontend/src/features/service/variable-utils.test.ts
T
Tomas DvorakandDevin 1d5b99e1ba feat(service): variables editor with masked-secret preservation
PUT /services/{id}/variables replaced every row, and GET masks secrets as
******** — echoing the fetched list back would have overwritten real
secrets with asterisks. The backend now keeps the stored value when a
submitted secret still carries the mask.

Service detail gains a Variables section: add/edit/remove rows, secret
toggle, bulk .env paste (comments, export prefix, quoted values), and
inline validation for empty/invalid/duplicate keys. Parser and validator
live in variable-utils.ts with unit coverage.

Generated OpenAPI types drive the new updateServiceVariables client call.
ROADMAP: Variables UX marked done; per-environment values are already
structural — each environment owns its service instances.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-17 10:49:45 +02:00

41 lines
1.3 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { parseDotenv, validateVariableRows } from './variable-utils';
describe('parseDotenv', () => {
it('parses KEY=VAL lines and skips blanks/comments', () => {
const rows = parseDotenv('A=1\n\n# comment\nB=two\n');
expect(rows).toEqual([
{ key: 'A', value: '1', isSecret: false },
{ key: 'B', value: 'two', isSecret: false },
]);
});
it('strips export prefix and quotes, keeps = inside values', () => {
const rows = parseDotenv('export A="x=y"\nB=\' spaced \'\nC=plain\n');
expect(rows.map((r) => [r.key, r.value])).toEqual([
['A', 'x=y'],
['B', ' spaced '],
['C', 'plain'],
]);
});
it('ignores malformed lines without a key', () => {
expect(parseDotenv('=novalue\njusttext\n')).toEqual([]);
});
});
describe('validateVariableRows', () => {
it('flags empty, invalid, and duplicate keys', () => {
const errors = validateVariableRows([
{ key: 'OK', value: '1', isSecret: false },
{ key: '', value: 'x', isSecret: false },
{ key: '9BAD', value: 'x', isSecret: false },
{ key: 'OK', value: '2', isSecret: false },
]);
expect(errors[0]).toBeUndefined();
expect(errors[1]).toBe('Key is required');
expect(errors[2]).toContain('Letters, digits');
expect(errors[3]).toBe('Duplicate key');
});
});