82 lines
3.8 KiB
TypeScript
82 lines
3.8 KiB
TypeScript
import type { CanvasComponent, ProjectDocument, RestAction } from '../../types/project';
|
|
import {
|
|
createResponseBinding,
|
|
findVariableReferences,
|
|
parseVariableDefault,
|
|
removeBindingAt,
|
|
removeVariable,
|
|
responseTargetOptions,
|
|
setVariable,
|
|
validateVariableName,
|
|
} from './configurationUtils';
|
|
|
|
const action: RestAction = {
|
|
id: 'action_lookup', name: 'Lookup', method: 'GET', url: 'https://example.com',
|
|
headers: {}, queryParameters: {}, pathParameters: {}, bodyTemplate: '', authenticationType: 'anonymous',
|
|
};
|
|
|
|
const components: CanvasComponent[] = [
|
|
{ id: 'label', type: 'Label', name: 'status', position: { x: 0, y: 0 }, size: { width: 10, height: 10 }, properties: {} },
|
|
{ id: 'dropdown', type: 'Dropdown', name: 'choices', position: { x: 0, y: 0 }, size: { width: 10, height: 10 }, properties: {} },
|
|
{ id: 'input', type: 'TextInput', name: 'query', position: { x: 0, y: 0 }, size: { width: 10, height: 10 }, properties: {} },
|
|
];
|
|
|
|
const doc: ProjectDocument = {
|
|
schemaVersion: '0.1.0',
|
|
project: { id: 'p', name: 'P', pages: [], actions: [action], bindings: [], variables: {}, settings: {} },
|
|
};
|
|
|
|
test('creates canonical action-response bindings with onSuccess and a unique ID', () => {
|
|
const first = createResponseBinding([], action, 'components.status.value');
|
|
const second = createResponseBinding([first], action, 'variables.result');
|
|
expect(first).toEqual({ id: 'binding_response_1', source: 'actions.action_lookup.response.body', target: 'components.status.value', trigger: 'onSuccess' });
|
|
expect(second.id).toBe('binding_response_2');
|
|
});
|
|
|
|
test('offers only runtime-supported component targets plus variables', () => {
|
|
expect(responseTargetOptions(components, { result: { type: 'object' } })).toEqual([
|
|
{ value: 'components.status.value', label: 'status (Label.value)' },
|
|
{ value: 'components.choices.options', label: 'choices (Dropdown.options)' },
|
|
{ value: 'variables.result', label: 'result (variable)' },
|
|
]);
|
|
});
|
|
|
|
test('does not offer ambiguous duplicate component names as new targets', () => {
|
|
expect(responseTargetOptions([
|
|
components[0],
|
|
{ ...components[0], id: 'other-label' },
|
|
], {})).toEqual([]);
|
|
});
|
|
|
|
test('parses typed defaults and reports invalid declarations', () => {
|
|
expect(parseVariableDefault('string', '5')).toBe('5');
|
|
expect(parseVariableDefault('number', '5')).toBe(5);
|
|
expect(parseVariableDefault('boolean', 'false')).toBe(false);
|
|
expect(parseVariableDefault('array', '[1,2]')).toEqual([1, 2]);
|
|
expect(() => parseVariableDefault('object', '[]')).toThrow('JSON object');
|
|
expect(validateVariableName('bad.name', {})).not.toBeNull();
|
|
expect(validateVariableName('result', { result: { type: 'string' } })).toContain('already exists');
|
|
});
|
|
|
|
test('writes and removes variables and bindings without touching other canonical state', () => {
|
|
const withVariable = setVariable(doc, 'result', { type: 'string', defaultValue: 'ready' });
|
|
const binding = createResponseBinding([], action, 'variables.result');
|
|
const withBinding = { ...withVariable, project: { ...withVariable.project, bindings: [binding] } };
|
|
expect(removeBindingAt(withBinding, 0).project.bindings).toEqual([]);
|
|
expect(removeVariable(withVariable, 'result').project.variables).toEqual({});
|
|
expect(withVariable.project.actions).toBe(doc.project.actions);
|
|
});
|
|
|
|
test('finds binding and request-template references before variable deletion', () => {
|
|
const referenced: ProjectDocument = {
|
|
...doc,
|
|
project: {
|
|
...doc.project,
|
|
actions: [{ ...action, queryParameters: { item: '{{variables.result}}' }, pathParameters: { legacy: '{{variables.result}}' } }],
|
|
bindings: [{ id: 'b', source: 'actions.action_lookup.response', target: 'variables.result', trigger: 'onSuccess' }],
|
|
variables: { result: { type: 'string' } },
|
|
},
|
|
};
|
|
expect(findVariableReferences(referenced, 'result')).toEqual(['binding "b"', 'action "Lookup"']);
|
|
});
|