mirror of
https://github.com/langgenius/dify.git
synced 2025-11-24 08:52:43 +00:00
820 lines
21 KiB
TypeScript
820 lines
21 KiB
TypeScript
|
|
/**
|
||
|
|
* Test suite for model configuration transformation utilities
|
||
|
|
*
|
||
|
|
* This module handles the conversion between two different representations of user input forms:
|
||
|
|
* 1. UserInputFormItem: The form structure used in the UI
|
||
|
|
* 2. PromptVariable: The variable structure used in prompts and model configuration
|
||
|
|
*
|
||
|
|
* Key functions:
|
||
|
|
* - userInputsFormToPromptVariables: Converts UI form items to prompt variables
|
||
|
|
* - promptVariablesToUserInputsForm: Converts prompt variables back to form items
|
||
|
|
* - formatBooleanInputs: Ensures boolean inputs are properly typed
|
||
|
|
*/
|
||
|
|
import {
|
||
|
|
formatBooleanInputs,
|
||
|
|
promptVariablesToUserInputsForm,
|
||
|
|
userInputsFormToPromptVariables,
|
||
|
|
} from './model-config'
|
||
|
|
import type { UserInputFormItem } from '@/types/app'
|
||
|
|
import type { PromptVariable } from '@/models/debug'
|
||
|
|
|
||
|
|
describe('Model Config Utilities', () => {
|
||
|
|
describe('userInputsFormToPromptVariables', () => {
|
||
|
|
/**
|
||
|
|
* Test handling of null or undefined input
|
||
|
|
* Should return empty array when no inputs provided
|
||
|
|
*/
|
||
|
|
it('should return empty array for null input', () => {
|
||
|
|
const result = userInputsFormToPromptVariables(null)
|
||
|
|
expect(result).toEqual([])
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of text-input (string) type
|
||
|
|
* Text inputs are the most common form field type
|
||
|
|
*/
|
||
|
|
it('should convert text-input to string prompt variable', () => {
|
||
|
|
const userInputs: UserInputFormItem[] = [
|
||
|
|
{
|
||
|
|
'text-input': {
|
||
|
|
label: 'User Name',
|
||
|
|
variable: 'user_name',
|
||
|
|
required: true,
|
||
|
|
max_length: 100,
|
||
|
|
default: '',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = userInputsFormToPromptVariables(userInputs)
|
||
|
|
|
||
|
|
expect(result).toHaveLength(1)
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
key: 'user_name',
|
||
|
|
name: 'User Name',
|
||
|
|
required: true,
|
||
|
|
type: 'string',
|
||
|
|
max_length: 100,
|
||
|
|
options: [],
|
||
|
|
is_context_var: false,
|
||
|
|
hide: false,
|
||
|
|
default: '',
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of paragraph type
|
||
|
|
* Paragraphs are multi-line text inputs
|
||
|
|
*/
|
||
|
|
it('should convert paragraph to paragraph prompt variable', () => {
|
||
|
|
const userInputs: UserInputFormItem[] = [
|
||
|
|
{
|
||
|
|
paragraph: {
|
||
|
|
label: 'Description',
|
||
|
|
variable: 'description',
|
||
|
|
required: false,
|
||
|
|
max_length: 500,
|
||
|
|
default: '',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = userInputsFormToPromptVariables(userInputs)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
key: 'description',
|
||
|
|
name: 'Description',
|
||
|
|
required: false,
|
||
|
|
type: 'paragraph',
|
||
|
|
max_length: 500,
|
||
|
|
options: [],
|
||
|
|
is_context_var: false,
|
||
|
|
hide: false,
|
||
|
|
default: '',
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of number type
|
||
|
|
* Number inputs should preserve numeric constraints
|
||
|
|
*/
|
||
|
|
it('should convert number input to number prompt variable', () => {
|
||
|
|
const userInputs: UserInputFormItem[] = [
|
||
|
|
{
|
||
|
|
number: {
|
||
|
|
label: 'Age',
|
||
|
|
variable: 'age',
|
||
|
|
required: true,
|
||
|
|
default: '',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
} as any,
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = userInputsFormToPromptVariables(userInputs)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
key: 'age',
|
||
|
|
name: 'Age',
|
||
|
|
required: true,
|
||
|
|
type: 'number',
|
||
|
|
options: [],
|
||
|
|
hide: false,
|
||
|
|
default: '',
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of checkbox (boolean) type
|
||
|
|
* Checkboxes are converted to 'checkbox' type in prompt variables
|
||
|
|
*/
|
||
|
|
it('should convert checkbox to checkbox prompt variable', () => {
|
||
|
|
const userInputs: UserInputFormItem[] = [
|
||
|
|
{
|
||
|
|
checkbox: {
|
||
|
|
label: 'Accept Terms',
|
||
|
|
variable: 'accept_terms',
|
||
|
|
required: true,
|
||
|
|
default: '',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
} as any,
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = userInputsFormToPromptVariables(userInputs)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
key: 'accept_terms',
|
||
|
|
name: 'Accept Terms',
|
||
|
|
required: true,
|
||
|
|
type: 'checkbox',
|
||
|
|
options: [],
|
||
|
|
hide: false,
|
||
|
|
default: '',
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of select (dropdown) type
|
||
|
|
* Select inputs include options array
|
||
|
|
*/
|
||
|
|
it('should convert select input to select prompt variable', () => {
|
||
|
|
const userInputs: UserInputFormItem[] = [
|
||
|
|
{
|
||
|
|
select: {
|
||
|
|
label: 'Country',
|
||
|
|
variable: 'country',
|
||
|
|
required: true,
|
||
|
|
options: ['USA', 'Canada', 'Mexico'],
|
||
|
|
default: 'USA',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = userInputsFormToPromptVariables(userInputs)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
key: 'country',
|
||
|
|
name: 'Country',
|
||
|
|
required: true,
|
||
|
|
type: 'select',
|
||
|
|
options: ['USA', 'Canada', 'Mexico'],
|
||
|
|
is_context_var: false,
|
||
|
|
hide: false,
|
||
|
|
default: 'USA',
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of file upload type
|
||
|
|
* File inputs include configuration for allowed types and upload methods
|
||
|
|
*/
|
||
|
|
it('should convert file input to file prompt variable', () => {
|
||
|
|
const userInputs: UserInputFormItem[] = [
|
||
|
|
{
|
||
|
|
file: {
|
||
|
|
label: 'Profile Picture',
|
||
|
|
variable: 'profile_pic',
|
||
|
|
required: false,
|
||
|
|
allowed_file_types: ['image'],
|
||
|
|
allowed_file_extensions: ['.jpg', '.png'],
|
||
|
|
allowed_file_upload_methods: ['local_file', 'remote_url'],
|
||
|
|
default: '',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
} as any,
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = userInputsFormToPromptVariables(userInputs)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
key: 'profile_pic',
|
||
|
|
name: 'Profile Picture',
|
||
|
|
required: false,
|
||
|
|
type: 'file',
|
||
|
|
config: {
|
||
|
|
allowed_file_types: ['image'],
|
||
|
|
allowed_file_extensions: ['.jpg', '.png'],
|
||
|
|
allowed_file_upload_methods: ['local_file', 'remote_url'],
|
||
|
|
number_limits: 1,
|
||
|
|
},
|
||
|
|
hide: false,
|
||
|
|
default: '',
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of file-list type
|
||
|
|
* File lists allow multiple file uploads with a max_length constraint
|
||
|
|
*/
|
||
|
|
it('should convert file-list input to file-list prompt variable', () => {
|
||
|
|
const userInputs: UserInputFormItem[] = [
|
||
|
|
{
|
||
|
|
'file-list': {
|
||
|
|
label: 'Documents',
|
||
|
|
variable: 'documents',
|
||
|
|
required: true,
|
||
|
|
allowed_file_types: ['document'],
|
||
|
|
allowed_file_extensions: ['.pdf', '.docx'],
|
||
|
|
allowed_file_upload_methods: ['local_file'],
|
||
|
|
max_length: 5,
|
||
|
|
default: '',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
} as any,
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = userInputsFormToPromptVariables(userInputs)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
key: 'documents',
|
||
|
|
name: 'Documents',
|
||
|
|
required: true,
|
||
|
|
type: 'file-list',
|
||
|
|
config: {
|
||
|
|
allowed_file_types: ['document'],
|
||
|
|
allowed_file_extensions: ['.pdf', '.docx'],
|
||
|
|
allowed_file_upload_methods: ['local_file'],
|
||
|
|
number_limits: 5,
|
||
|
|
},
|
||
|
|
hide: false,
|
||
|
|
default: '',
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of external_data_tool type
|
||
|
|
* External data tools have custom configuration and icons
|
||
|
|
*/
|
||
|
|
it('should convert external_data_tool to prompt variable', () => {
|
||
|
|
const userInputs: UserInputFormItem[] = [
|
||
|
|
{
|
||
|
|
external_data_tool: {
|
||
|
|
label: 'API Data',
|
||
|
|
variable: 'api_data',
|
||
|
|
type: 'api',
|
||
|
|
enabled: true,
|
||
|
|
required: false,
|
||
|
|
config: { endpoint: 'https://api.example.com' },
|
||
|
|
icon: 'api-icon',
|
||
|
|
icon_background: '#FF5733',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
} as any,
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = userInputsFormToPromptVariables(userInputs)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
key: 'api_data',
|
||
|
|
name: 'API Data',
|
||
|
|
required: false,
|
||
|
|
type: 'api',
|
||
|
|
enabled: true,
|
||
|
|
config: { endpoint: 'https://api.example.com' },
|
||
|
|
icon: 'api-icon',
|
||
|
|
icon_background: '#FF5733',
|
||
|
|
is_context_var: false,
|
||
|
|
hide: false,
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test handling of dataset_query_variable
|
||
|
|
* When a variable matches the dataset_query_variable, is_context_var should be true
|
||
|
|
*/
|
||
|
|
it('should mark variable as context var when matching dataset_query_variable', () => {
|
||
|
|
const userInputs: UserInputFormItem[] = [
|
||
|
|
{
|
||
|
|
'text-input': {
|
||
|
|
label: 'Query',
|
||
|
|
variable: 'query',
|
||
|
|
required: true,
|
||
|
|
max_length: 200,
|
||
|
|
default: '',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = userInputsFormToPromptVariables(userInputs, 'query')
|
||
|
|
|
||
|
|
expect(result[0].is_context_var).toBe(true)
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of multiple mixed input types
|
||
|
|
* Should handle an array with different input types correctly
|
||
|
|
*/
|
||
|
|
it('should convert multiple mixed input types', () => {
|
||
|
|
const userInputs: UserInputFormItem[] = [
|
||
|
|
{
|
||
|
|
'text-input': {
|
||
|
|
label: 'Name',
|
||
|
|
variable: 'name',
|
||
|
|
required: true,
|
||
|
|
max_length: 50,
|
||
|
|
default: '',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
number: {
|
||
|
|
label: 'Age',
|
||
|
|
variable: 'age',
|
||
|
|
required: false,
|
||
|
|
default: '',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
} as any,
|
||
|
|
{
|
||
|
|
select: {
|
||
|
|
label: 'Gender',
|
||
|
|
variable: 'gender',
|
||
|
|
required: true,
|
||
|
|
options: ['Male', 'Female', 'Other'],
|
||
|
|
default: '',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = userInputsFormToPromptVariables(userInputs)
|
||
|
|
|
||
|
|
expect(result).toHaveLength(3)
|
||
|
|
expect(result[0].type).toBe('string')
|
||
|
|
expect(result[1].type).toBe('number')
|
||
|
|
expect(result[2].type).toBe('select')
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
describe('promptVariablesToUserInputsForm', () => {
|
||
|
|
/**
|
||
|
|
* Test conversion of string prompt variable back to text-input
|
||
|
|
*/
|
||
|
|
it('should convert string prompt variable to text-input', () => {
|
||
|
|
const promptVariables: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: 'user_name',
|
||
|
|
name: 'User Name',
|
||
|
|
required: true,
|
||
|
|
type: 'string',
|
||
|
|
max_length: 100,
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = promptVariablesToUserInputsForm(promptVariables)
|
||
|
|
|
||
|
|
expect(result).toHaveLength(1)
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
'text-input': {
|
||
|
|
label: 'User Name',
|
||
|
|
variable: 'user_name',
|
||
|
|
required: true,
|
||
|
|
max_length: 100,
|
||
|
|
default: '',
|
||
|
|
hide: undefined,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of paragraph prompt variable
|
||
|
|
*/
|
||
|
|
it('should convert paragraph prompt variable to paragraph input', () => {
|
||
|
|
const promptVariables: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: 'description',
|
||
|
|
name: 'Description',
|
||
|
|
required: false,
|
||
|
|
type: 'paragraph',
|
||
|
|
max_length: 500,
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = promptVariablesToUserInputsForm(promptVariables)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
paragraph: {
|
||
|
|
label: 'Description',
|
||
|
|
variable: 'description',
|
||
|
|
required: false,
|
||
|
|
max_length: 500,
|
||
|
|
default: '',
|
||
|
|
hide: undefined,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of number prompt variable
|
||
|
|
*/
|
||
|
|
it('should convert number prompt variable to number input', () => {
|
||
|
|
const promptVariables: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: 'age',
|
||
|
|
name: 'Age',
|
||
|
|
required: true,
|
||
|
|
type: 'number',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = promptVariablesToUserInputsForm(promptVariables)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
number: {
|
||
|
|
label: 'Age',
|
||
|
|
variable: 'age',
|
||
|
|
required: true,
|
||
|
|
default: '',
|
||
|
|
hide: undefined,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of checkbox prompt variable
|
||
|
|
*/
|
||
|
|
it('should convert checkbox prompt variable to checkbox input', () => {
|
||
|
|
const promptVariables: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: 'accept_terms',
|
||
|
|
name: 'Accept Terms',
|
||
|
|
required: true,
|
||
|
|
type: 'checkbox',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = promptVariablesToUserInputsForm(promptVariables)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
checkbox: {
|
||
|
|
label: 'Accept Terms',
|
||
|
|
variable: 'accept_terms',
|
||
|
|
required: true,
|
||
|
|
default: '',
|
||
|
|
hide: undefined,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of select prompt variable
|
||
|
|
*/
|
||
|
|
it('should convert select prompt variable to select input', () => {
|
||
|
|
const promptVariables: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: 'country',
|
||
|
|
name: 'Country',
|
||
|
|
required: true,
|
||
|
|
type: 'select',
|
||
|
|
options: ['USA', 'Canada', 'Mexico'],
|
||
|
|
default: 'USA',
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = promptVariablesToUserInputsForm(promptVariables)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
select: {
|
||
|
|
label: 'Country',
|
||
|
|
variable: 'country',
|
||
|
|
required: true,
|
||
|
|
options: ['USA', 'Canada', 'Mexico'],
|
||
|
|
default: 'USA',
|
||
|
|
hide: undefined,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test filtering of invalid prompt variables
|
||
|
|
* Variables without key or name should be filtered out
|
||
|
|
*/
|
||
|
|
it('should filter out variables with empty key or name', () => {
|
||
|
|
const promptVariables: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: '',
|
||
|
|
name: 'Empty Key',
|
||
|
|
required: true,
|
||
|
|
type: 'string',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'valid',
|
||
|
|
name: '',
|
||
|
|
required: true,
|
||
|
|
type: 'string',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: ' ',
|
||
|
|
name: 'Whitespace Key',
|
||
|
|
required: true,
|
||
|
|
type: 'string',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'valid_key',
|
||
|
|
name: 'Valid Name',
|
||
|
|
required: true,
|
||
|
|
type: 'string',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = promptVariablesToUserInputsForm(promptVariables)
|
||
|
|
|
||
|
|
expect(result).toHaveLength(1)
|
||
|
|
expect((result[0] as any)['text-input']?.variable).toBe('valid_key')
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of external data tool prompt variable
|
||
|
|
*/
|
||
|
|
it('should convert external data tool prompt variable', () => {
|
||
|
|
const promptVariables: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: 'api_data',
|
||
|
|
name: 'API Data',
|
||
|
|
required: false,
|
||
|
|
type: 'api',
|
||
|
|
enabled: true,
|
||
|
|
config: { endpoint: 'https://api.example.com' },
|
||
|
|
icon: 'api-icon',
|
||
|
|
icon_background: '#FF5733',
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = promptVariablesToUserInputsForm(promptVariables)
|
||
|
|
|
||
|
|
expect(result[0]).toEqual({
|
||
|
|
external_data_tool: {
|
||
|
|
label: 'API Data',
|
||
|
|
variable: 'api_data',
|
||
|
|
enabled: true,
|
||
|
|
type: 'api',
|
||
|
|
config: { endpoint: 'https://api.example.com' },
|
||
|
|
required: false,
|
||
|
|
icon: 'api-icon',
|
||
|
|
icon_background: '#FF5733',
|
||
|
|
hide: undefined,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test that required defaults to true when not explicitly set to false
|
||
|
|
*/
|
||
|
|
it('should default required to true when not false', () => {
|
||
|
|
const promptVariables: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: 'test1',
|
||
|
|
name: 'Test 1',
|
||
|
|
required: undefined,
|
||
|
|
type: 'string',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'test2',
|
||
|
|
name: 'Test 2',
|
||
|
|
required: false,
|
||
|
|
type: 'string',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const result = promptVariablesToUserInputsForm(promptVariables)
|
||
|
|
|
||
|
|
expect((result[0] as any)['text-input']?.required).toBe(true)
|
||
|
|
expect((result[1] as any)['text-input']?.required).toBe(false)
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
describe('formatBooleanInputs', () => {
|
||
|
|
/**
|
||
|
|
* Test that null or undefined inputs are handled gracefully
|
||
|
|
*/
|
||
|
|
it('should return inputs unchanged when useInputs is null', () => {
|
||
|
|
const inputs = { key1: 'value1', key2: 'value2' }
|
||
|
|
const result = formatBooleanInputs(null, inputs)
|
||
|
|
expect(result).toEqual(inputs)
|
||
|
|
})
|
||
|
|
|
||
|
|
it('should return inputs unchanged when useInputs is undefined', () => {
|
||
|
|
const inputs = { key1: 'value1', key2: 'value2' }
|
||
|
|
const result = formatBooleanInputs(undefined, inputs)
|
||
|
|
expect(result).toEqual(inputs)
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test conversion of boolean input values to actual boolean type
|
||
|
|
* This is important for proper type handling in the backend
|
||
|
|
* Note: checkbox inputs are converted to type 'checkbox' by userInputsFormToPromptVariables
|
||
|
|
*/
|
||
|
|
it('should convert boolean inputs to boolean type', () => {
|
||
|
|
const useInputs: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: 'accept_terms',
|
||
|
|
name: 'Accept Terms',
|
||
|
|
required: true,
|
||
|
|
type: 'checkbox',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'subscribe',
|
||
|
|
name: 'Subscribe',
|
||
|
|
required: false,
|
||
|
|
type: 'checkbox',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const inputs = {
|
||
|
|
accept_terms: 'true',
|
||
|
|
subscribe: '',
|
||
|
|
other_field: 'value',
|
||
|
|
}
|
||
|
|
|
||
|
|
const result = formatBooleanInputs(useInputs, inputs)
|
||
|
|
|
||
|
|
expect(result).toEqual({
|
||
|
|
accept_terms: true,
|
||
|
|
subscribe: false,
|
||
|
|
other_field: 'value',
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test that non-boolean inputs are not affected
|
||
|
|
*/
|
||
|
|
it('should not modify non-boolean inputs', () => {
|
||
|
|
const useInputs: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: 'name',
|
||
|
|
name: 'Name',
|
||
|
|
required: true,
|
||
|
|
type: 'string',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'age',
|
||
|
|
name: 'Age',
|
||
|
|
required: true,
|
||
|
|
type: 'number',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const inputs = {
|
||
|
|
name: 'John Doe',
|
||
|
|
age: 30,
|
||
|
|
}
|
||
|
|
|
||
|
|
const result = formatBooleanInputs(useInputs, inputs)
|
||
|
|
|
||
|
|
expect(result).toEqual(inputs)
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test handling of truthy and falsy values for boolean conversion
|
||
|
|
* Note: checkbox inputs are converted to type 'checkbox' by userInputsFormToPromptVariables
|
||
|
|
*/
|
||
|
|
it('should handle various truthy and falsy values', () => {
|
||
|
|
const useInputs: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: 'bool1',
|
||
|
|
name: 'Bool 1',
|
||
|
|
required: true,
|
||
|
|
type: 'checkbox',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'bool2',
|
||
|
|
name: 'Bool 2',
|
||
|
|
required: true,
|
||
|
|
type: 'checkbox',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'bool3',
|
||
|
|
name: 'Bool 3',
|
||
|
|
required: true,
|
||
|
|
type: 'checkbox',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
key: 'bool4',
|
||
|
|
name: 'Bool 4',
|
||
|
|
required: true,
|
||
|
|
type: 'checkbox',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const inputs = {
|
||
|
|
bool1: 1,
|
||
|
|
bool2: 0,
|
||
|
|
bool3: 'yes',
|
||
|
|
bool4: null as any,
|
||
|
|
}
|
||
|
|
|
||
|
|
const result = formatBooleanInputs(useInputs, inputs)
|
||
|
|
|
||
|
|
expect(result?.bool1).toBe(true)
|
||
|
|
expect(result?.bool2).toBe(false)
|
||
|
|
expect(result?.bool3).toBe(true)
|
||
|
|
expect(result?.bool4).toBe(false)
|
||
|
|
})
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test that the function creates a new object and doesn't mutate the original
|
||
|
|
* Note: checkbox inputs are converted to type 'checkbox' by userInputsFormToPromptVariables
|
||
|
|
*/
|
||
|
|
it('should not mutate original inputs object', () => {
|
||
|
|
const useInputs: PromptVariable[] = [
|
||
|
|
{
|
||
|
|
key: 'flag',
|
||
|
|
name: 'Flag',
|
||
|
|
required: true,
|
||
|
|
type: 'checkbox',
|
||
|
|
options: [],
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const inputs = { flag: 'true', other: 'value' }
|
||
|
|
const originalInputs = { ...inputs }
|
||
|
|
|
||
|
|
formatBooleanInputs(useInputs, inputs)
|
||
|
|
|
||
|
|
expect(inputs).toEqual(originalInputs)
|
||
|
|
})
|
||
|
|
})
|
||
|
|
|
||
|
|
describe('Round-trip conversion', () => {
|
||
|
|
/**
|
||
|
|
* Test that converting from UserInputForm to PromptVariable and back
|
||
|
|
* preserves the essential data (though some fields may have defaults applied)
|
||
|
|
*/
|
||
|
|
it('should preserve data through round-trip conversion', () => {
|
||
|
|
const originalUserInputs: UserInputFormItem[] = [
|
||
|
|
{
|
||
|
|
'text-input': {
|
||
|
|
label: 'Name',
|
||
|
|
variable: 'name',
|
||
|
|
required: true,
|
||
|
|
max_length: 50,
|
||
|
|
default: '',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
select: {
|
||
|
|
label: 'Type',
|
||
|
|
variable: 'type',
|
||
|
|
required: false,
|
||
|
|
options: ['A', 'B', 'C'],
|
||
|
|
default: 'A',
|
||
|
|
hide: false,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const promptVars = userInputsFormToPromptVariables(originalUserInputs)
|
||
|
|
const backToUserInputs = promptVariablesToUserInputsForm(promptVars)
|
||
|
|
|
||
|
|
expect(backToUserInputs).toHaveLength(2)
|
||
|
|
expect((backToUserInputs[0] as any)['text-input']?.variable).toBe('name')
|
||
|
|
expect((backToUserInputs[1] as any).select?.variable).toBe('type')
|
||
|
|
expect((backToUserInputs[1] as any).select?.options).toEqual(['A', 'B', 'C'])
|
||
|
|
})
|
||
|
|
})
|
||
|
|
})
|