Support define is tool logic function (#17926)
- supports isTool and timeout settings in defineLogicFunction in apps and in setting tabs definition - compute for all toolInputSchema for logic funciton, in settings and in code steps <img width="991" height="802" alt="image" src="https://github.com/user-attachments/assets/05dc1221-cac9-45a3-87b0-3b13161446fd" />
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`generateDepthRecordGqlFieldsFromObject should generate depth one record gql fields from object 1`] = `
|
||||
{
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
import {
|
||||
isFieldAddressValue,
|
||||
addressSchema,
|
||||
} from '@/object-record/record-field/ui/types/guards/isFieldAddressValue';
|
||||
|
||||
describe('isFieldAddressValue', () => {
|
||||
it('should return true for valid address values', () => {
|
||||
expect(
|
||||
isFieldAddressValue({
|
||||
addressStreet1: '123 Main St',
|
||||
addressStreet2: null,
|
||||
addressCity: 'Paris',
|
||||
addressState: null,
|
||||
addressPostcode: '75001',
|
||||
addressCountry: 'France',
|
||||
addressLat: 48.8566,
|
||||
addressLng: 2.3522,
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for minimal address with all nullable fields null', () => {
|
||||
expect(
|
||||
isFieldAddressValue({
|
||||
addressStreet1: '',
|
||||
addressStreet2: null,
|
||||
addressCity: null,
|
||||
addressState: null,
|
||||
addressPostcode: null,
|
||||
addressCountry: null,
|
||||
addressLat: null,
|
||||
addressLng: null,
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for incomplete address', () => {
|
||||
expect(isFieldAddressValue({ addressStreet1: '123 Main St' })).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for non-object values', () => {
|
||||
expect(isFieldAddressValue(null)).toBe(false);
|
||||
expect(isFieldAddressValue('address')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('addressSchema', () => {
|
||||
it('should parse a valid address', () => {
|
||||
const result = addressSchema.safeParse({
|
||||
addressStreet1: '123 Main St',
|
||||
addressStreet2: null,
|
||||
addressCity: 'Paris',
|
||||
addressState: null,
|
||||
addressPostcode: '75001',
|
||||
addressCountry: 'France',
|
||||
addressLat: null,
|
||||
addressLng: null,
|
||||
});
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
});
|
||||
});
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { isFieldArrayValue } from '@/object-record/record-field/ui/types/guards/isFieldArrayValue';
|
||||
|
||||
describe('isFieldArrayValue', () => {
|
||||
it('should return true for string arrays', () => {
|
||||
expect(isFieldArrayValue(['a', 'b', 'c'])).toBe(true);
|
||||
expect(isFieldArrayValue([])).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for null', () => {
|
||||
expect(isFieldArrayValue(null)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for non-array values', () => {
|
||||
expect(isFieldArrayValue('string')).toBe(false);
|
||||
expect(isFieldArrayValue(42)).toBe(false);
|
||||
expect(isFieldArrayValue(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for arrays of non-strings', () => {
|
||||
expect(isFieldArrayValue([1, 2, 3])).toBe(false);
|
||||
});
|
||||
});
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { isFieldBooleanValue } from '@/object-record/record-field/ui/types/guards/isFieldBooleanValue';
|
||||
|
||||
describe('isFieldBooleanValue', () => {
|
||||
it('should return true for boolean values', () => {
|
||||
expect(isFieldBooleanValue(true)).toBe(true);
|
||||
expect(isFieldBooleanValue(false)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for non-boolean values', () => {
|
||||
expect(isFieldBooleanValue('true')).toBe(false);
|
||||
expect(isFieldBooleanValue(1)).toBe(false);
|
||||
expect(isFieldBooleanValue(null)).toBe(false);
|
||||
expect(isFieldBooleanValue(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { isFieldCurrencyValue } from '@/object-record/record-field/ui/types/guards/isFieldCurrencyValue';
|
||||
|
||||
describe('isFieldCurrencyValue', () => {
|
||||
it('should return true for valid currency values', () => {
|
||||
expect(
|
||||
isFieldCurrencyValue({ currencyCode: 'USD', amountMicros: 1000000 }),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isFieldCurrencyValue({ currencyCode: null, amountMicros: null }),
|
||||
).toBe(true);
|
||||
expect(isFieldCurrencyValue({ currencyCode: '', amountMicros: null })).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return false for invalid currency values', () => {
|
||||
expect(isFieldCurrencyValue({ currencyCode: 'INVALID' })).toBe(false);
|
||||
expect(isFieldCurrencyValue(null)).toBe(false);
|
||||
expect(isFieldCurrencyValue('USD')).toBe(false);
|
||||
});
|
||||
});
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { isFieldDateValue } from '@/object-record/record-field/ui/types/guards/isFieldDateValue';
|
||||
|
||||
describe('isFieldDateValue', () => {
|
||||
it('should return true for valid date strings', () => {
|
||||
expect(isFieldDateValue('2024-01-15')).toBe(true);
|
||||
expect(isFieldDateValue('2024-01-15T10:30:00Z')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for null', () => {
|
||||
expect(isFieldDateValue(null)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for invalid date strings', () => {
|
||||
expect(isFieldDateValue('not-a-date')).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for non-string values', () => {
|
||||
expect(isFieldDateValue(42)).toBe(false);
|
||||
expect(isFieldDateValue(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { isFieldFullNameValue } from '@/object-record/record-field/ui/types/guards/isFieldFullNameValue';
|
||||
|
||||
describe('isFieldFullNameValue', () => {
|
||||
it('should return true for valid full name objects', () => {
|
||||
expect(isFieldFullNameValue({ firstName: 'John', lastName: 'Doe' })).toBe(
|
||||
true,
|
||||
);
|
||||
expect(isFieldFullNameValue({ firstName: '', lastName: '' })).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for incomplete objects', () => {
|
||||
expect(isFieldFullNameValue({ firstName: 'John' })).toBe(false);
|
||||
expect(isFieldFullNameValue({ lastName: 'Doe' })).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for non-object values', () => {
|
||||
expect(isFieldFullNameValue('John Doe')).toBe(false);
|
||||
expect(isFieldFullNameValue(null)).toBe(false);
|
||||
expect(isFieldFullNameValue(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { isFieldNumberValue } from '@/object-record/record-field/ui/types/guards/isFieldNumberValue';
|
||||
|
||||
describe('isFieldNumberValue', () => {
|
||||
it('should return true for numbers', () => {
|
||||
expect(isFieldNumberValue(42)).toBe(true);
|
||||
expect(isFieldNumberValue(0)).toBe(true);
|
||||
expect(isFieldNumberValue(-1.5)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for null', () => {
|
||||
expect(isFieldNumberValue(null)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for non-number values', () => {
|
||||
expect(isFieldNumberValue('42')).toBe(false);
|
||||
expect(isFieldNumberValue(undefined)).toBe(false);
|
||||
expect(isFieldNumberValue({})).toBe(false);
|
||||
});
|
||||
});
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { isFieldRawJsonValue } from '@/object-record/record-field/ui/types/guards/isFieldRawJsonValue';
|
||||
|
||||
describe('isFieldRawJsonValue', () => {
|
||||
it('should return true for JSON objects', () => {
|
||||
expect(isFieldRawJsonValue({ key: 'value' })).toBe(true);
|
||||
expect(isFieldRawJsonValue({ nested: { deep: true } })).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for JSON arrays', () => {
|
||||
expect(isFieldRawJsonValue([1, 2, 3])).toBe(true);
|
||||
expect(isFieldRawJsonValue([])).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for null', () => {
|
||||
expect(isFieldRawJsonValue(null)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for literal values other than null', () => {
|
||||
expect(isFieldRawJsonValue('string')).toBe(false);
|
||||
expect(isFieldRawJsonValue(42)).toBe(false);
|
||||
expect(isFieldRawJsonValue(true)).toBe(false);
|
||||
});
|
||||
});
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { isFieldTextValue } from '@/object-record/record-field/ui/types/guards/isFieldTextValue';
|
||||
|
||||
describe('isFieldTextValue', () => {
|
||||
it('should return true for strings', () => {
|
||||
expect(isFieldTextValue('hello')).toBe(true);
|
||||
expect(isFieldTextValue('')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for non-string values', () => {
|
||||
expect(isFieldTextValue(42)).toBe(false);
|
||||
expect(isFieldTextValue(null)).toBe(false);
|
||||
expect(isFieldTextValue(undefined)).toBe(false);
|
||||
expect(isFieldTextValue(true)).toBe(false);
|
||||
});
|
||||
});
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
import { RecordGroupDefinitionType } from '@/object-record/record-group/types/RecordGroupDefinition';
|
||||
import { RecordGroupSort } from '@/object-record/record-group/types/RecordGroupSort';
|
||||
import { sortRecordGroupDefinitions } from '@/object-record/record-group/utils/sortRecordGroupDefinitions';
|
||||
|
||||
const createGroup = (
|
||||
overrides: Partial<{
|
||||
id: string;
|
||||
title: string;
|
||||
position: number;
|
||||
isVisible: boolean;
|
||||
}>,
|
||||
) => ({
|
||||
id: overrides.id ?? '1',
|
||||
type: RecordGroupDefinitionType.Value,
|
||||
title: overrides.title ?? 'Group',
|
||||
value: 'value',
|
||||
color: 'green' as const,
|
||||
position: overrides.position ?? 0,
|
||||
isVisible: overrides.isVisible ?? true,
|
||||
});
|
||||
|
||||
describe('sortRecordGroupDefinitions', () => {
|
||||
const groups = [
|
||||
createGroup({ id: '1', title: 'Charlie', position: 2 }),
|
||||
createGroup({ id: '2', title: 'Alpha', position: 0 }),
|
||||
createGroup({ id: '3', title: 'Bravo', position: 1 }),
|
||||
];
|
||||
|
||||
it('should sort alphabetically', () => {
|
||||
const result = sortRecordGroupDefinitions(
|
||||
groups,
|
||||
RecordGroupSort.Alphabetical,
|
||||
);
|
||||
|
||||
expect(result.map((g) => g.title)).toEqual(['Alpha', 'Bravo', 'Charlie']);
|
||||
});
|
||||
|
||||
it('should sort reverse alphabetically', () => {
|
||||
const result = sortRecordGroupDefinitions(
|
||||
groups,
|
||||
RecordGroupSort.ReverseAlphabetical,
|
||||
);
|
||||
|
||||
expect(result.map((g) => g.title)).toEqual(['Charlie', 'Bravo', 'Alpha']);
|
||||
});
|
||||
|
||||
it('should sort by position for Manual sort', () => {
|
||||
const result = sortRecordGroupDefinitions(groups, RecordGroupSort.Manual);
|
||||
|
||||
expect(result.map((g) => g.title)).toEqual(['Alpha', 'Bravo', 'Charlie']);
|
||||
});
|
||||
|
||||
it('should filter out hidden groups', () => {
|
||||
const groupsWithHidden = [
|
||||
...groups,
|
||||
createGroup({ id: '4', title: 'Delta', position: 3, isVisible: false }),
|
||||
];
|
||||
|
||||
const result = sortRecordGroupDefinitions(
|
||||
groupsWithHidden,
|
||||
RecordGroupSort.Manual,
|
||||
);
|
||||
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result.find((g) => g.title === 'Delta')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
import { computeNewPositionOfDraggedRecord } from '@/object-record/utils/computeNewPositionOfDraggedRecord';
|
||||
|
||||
describe('computeNewPositionOfDraggedRecord', () => {
|
||||
const records = [
|
||||
{ id: 'a', position: 1 },
|
||||
{ id: 'b', position: 2 },
|
||||
{ id: 'c', position: 3 },
|
||||
{ id: 'd', position: 4 },
|
||||
];
|
||||
|
||||
it('should return same position when dragging to itself', () => {
|
||||
const result = computeNewPositionOfDraggedRecord({
|
||||
arrayOfRecordsWithPosition: records,
|
||||
idOfItemToMove: 'b',
|
||||
idOfTargetItem: 'b',
|
||||
isDroppedAfterList: false,
|
||||
});
|
||||
|
||||
expect(result).toBe(2);
|
||||
});
|
||||
|
||||
it('should return target position + 1 when dropped after list', () => {
|
||||
const result = computeNewPositionOfDraggedRecord({
|
||||
arrayOfRecordsWithPosition: records,
|
||||
idOfItemToMove: 'a',
|
||||
idOfTargetItem: 'd',
|
||||
isDroppedAfterList: true,
|
||||
});
|
||||
|
||||
expect(result).toBe(5);
|
||||
});
|
||||
|
||||
it('should return target position - 1 when moving to first position', () => {
|
||||
const result = computeNewPositionOfDraggedRecord({
|
||||
arrayOfRecordsWithPosition: records,
|
||||
idOfItemToMove: 'c',
|
||||
idOfTargetItem: 'a',
|
||||
isDroppedAfterList: false,
|
||||
});
|
||||
|
||||
expect(result).toBe(0);
|
||||
});
|
||||
|
||||
it('should compute intermediary position when moving after target', () => {
|
||||
const result = computeNewPositionOfDraggedRecord({
|
||||
arrayOfRecordsWithPosition: records,
|
||||
idOfItemToMove: 'a',
|
||||
idOfTargetItem: 'b',
|
||||
isDroppedAfterList: false,
|
||||
});
|
||||
|
||||
expect(result).toBe(2.5);
|
||||
});
|
||||
|
||||
it('should compute intermediary position when moving before target', () => {
|
||||
const result = computeNewPositionOfDraggedRecord({
|
||||
arrayOfRecordsWithPosition: records,
|
||||
idOfItemToMove: 'd',
|
||||
idOfTargetItem: 'c',
|
||||
isDroppedAfterList: false,
|
||||
});
|
||||
|
||||
expect(result).toBe(2.5);
|
||||
});
|
||||
|
||||
it('should throw when target item is not found', () => {
|
||||
expect(() =>
|
||||
computeNewPositionOfDraggedRecord({
|
||||
arrayOfRecordsWithPosition: records,
|
||||
idOfItemToMove: 'a',
|
||||
idOfTargetItem: 'unknown',
|
||||
isDroppedAfterList: false,
|
||||
}),
|
||||
).toThrow('Cannot find item to move for id : unknown');
|
||||
});
|
||||
|
||||
it('should handle item not in table moved before target', () => {
|
||||
const result = computeNewPositionOfDraggedRecord({
|
||||
arrayOfRecordsWithPosition: records,
|
||||
idOfItemToMove: 'new-item',
|
||||
idOfTargetItem: 'c',
|
||||
isDroppedAfterList: false,
|
||||
});
|
||||
|
||||
expect(result).toBe(2.5);
|
||||
});
|
||||
|
||||
it('should return target + 1 when moving after last item', () => {
|
||||
const result = computeNewPositionOfDraggedRecord({
|
||||
arrayOfRecordsWithPosition: records,
|
||||
idOfItemToMove: 'a',
|
||||
idOfTargetItem: 'd',
|
||||
isDroppedAfterList: false,
|
||||
});
|
||||
|
||||
expect(result).toBe(4 + 1);
|
||||
});
|
||||
});
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
|
||||
|
||||
describe('filterAvailableTableColumns', () => {
|
||||
const createColumnDefinition = (fieldName: string) =>
|
||||
({
|
||||
metadata: { fieldName },
|
||||
}) as any;
|
||||
|
||||
it('should return false for denied column names', () => {
|
||||
expect(
|
||||
filterAvailableTableColumns(createColumnDefinition('attachments')),
|
||||
).toBe(false);
|
||||
expect(
|
||||
filterAvailableTableColumns(createColumnDefinition('activities')),
|
||||
).toBe(false);
|
||||
expect(
|
||||
filterAvailableTableColumns(createColumnDefinition('timelineActivities')),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true for allowed column names', () => {
|
||||
expect(filterAvailableTableColumns(createColumnDefinition('name'))).toBe(
|
||||
true,
|
||||
);
|
||||
expect(filterAvailableTableColumns(createColumnDefinition('email'))).toBe(
|
||||
true,
|
||||
);
|
||||
expect(filterAvailableTableColumns(createColumnDefinition('phone'))).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import { getDropdownFocusIdForRecordField } from '@/object-record/utils/getDropdownFocusIdForRecordField';
|
||||
|
||||
describe('getDropdownFocusIdForRecordField', () => {
|
||||
it('should generate correct dropdown focus id for table-cell', () => {
|
||||
const result = getDropdownFocusIdForRecordField({
|
||||
recordId: 'record-123',
|
||||
fieldMetadataId: 'field-456',
|
||||
componentType: 'table-cell',
|
||||
instanceId: 'instance-789',
|
||||
});
|
||||
|
||||
expect(result).toBe(
|
||||
'dropdown-instance-789-table-cell-record-record-123-field-field-456',
|
||||
);
|
||||
});
|
||||
|
||||
it('should generate correct dropdown focus id for inline-cell', () => {
|
||||
const result = getDropdownFocusIdForRecordField({
|
||||
recordId: 'record-abc',
|
||||
fieldMetadataId: 'field-def',
|
||||
componentType: 'inline-cell',
|
||||
instanceId: 'instance-ghi',
|
||||
});
|
||||
|
||||
expect(result).toBe(
|
||||
'dropdown-instance-ghi-inline-cell-record-record-abc-field-field-def',
|
||||
);
|
||||
});
|
||||
});
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
import { getQueryIdentifier } from '@/object-record/utils/getQueryIdentifier';
|
||||
|
||||
describe('getQueryIdentifier', () => {
|
||||
it('should create identifier from object name and variables', () => {
|
||||
const result = getQueryIdentifier({
|
||||
objectNameSingular: 'person',
|
||||
filter: { name: { eq: 'Alice' } },
|
||||
orderBy: [{ name: 'AscNullsFirst' }],
|
||||
limit: 10,
|
||||
});
|
||||
|
||||
expect(result).toContain('person');
|
||||
expect(result).toContain('Alice');
|
||||
expect(result).toContain('10');
|
||||
});
|
||||
|
||||
it('should include cursor filter when present', () => {
|
||||
const result = getQueryIdentifier({
|
||||
objectNameSingular: 'company',
|
||||
filter: {},
|
||||
orderBy: [],
|
||||
limit: 20,
|
||||
cursorFilter: { cursor: 'cursor-123', cursorDirection: 'before' },
|
||||
});
|
||||
|
||||
expect(result).toContain('cursor-123');
|
||||
});
|
||||
|
||||
it('should include groupBy when present', () => {
|
||||
const result = getQueryIdentifier({
|
||||
objectNameSingular: 'task',
|
||||
filter: {},
|
||||
orderBy: [],
|
||||
limit: 10,
|
||||
groupBy: [{ status: 'Done' }],
|
||||
});
|
||||
|
||||
expect(result).toContain('Done');
|
||||
});
|
||||
|
||||
it('should produce different identifiers for different filters', () => {
|
||||
const resultA = getQueryIdentifier({
|
||||
objectNameSingular: 'person',
|
||||
filter: { name: { eq: 'Alice' } },
|
||||
orderBy: [],
|
||||
limit: 10,
|
||||
});
|
||||
|
||||
const resultB = getQueryIdentifier({
|
||||
objectNameSingular: 'person',
|
||||
filter: { name: { eq: 'Bob' } },
|
||||
orderBy: [],
|
||||
limit: 10,
|
||||
});
|
||||
|
||||
expect(resultA).not.toBe(resultB);
|
||||
});
|
||||
});
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { getUpdateOneRecordMutationResponseField } from '@/object-record/utils/getUpdateOneRecordMutationResponseField';
|
||||
|
||||
describe('getUpdateOneRecordMutationResponseField', () => {
|
||||
it('should capitalize and prefix with "update"', () => {
|
||||
expect(getUpdateOneRecordMutationResponseField('person')).toBe(
|
||||
'updatePerson',
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle multi-word object names', () => {
|
||||
expect(getUpdateOneRecordMutationResponseField('company')).toBe(
|
||||
'updateCompany',
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle already capitalized names', () => {
|
||||
expect(getUpdateOneRecordMutationResponseField('Person')).toBe(
|
||||
'updatePerson',
|
||||
);
|
||||
});
|
||||
});
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { getUpdatedFieldsFromRecordInput } from '@/object-record/utils/getUpdatedFieldsFromRecordInput';
|
||||
|
||||
describe('getUpdatedFieldsFromRecordInput', () => {
|
||||
it('should return field entries excluding id', () => {
|
||||
const input = { id: '123', name: 'Alice', age: 30 };
|
||||
|
||||
const result = getUpdatedFieldsFromRecordInput(input);
|
||||
|
||||
expect(result).toEqual([{ name: 'Alice' }, { age: 30 }]);
|
||||
});
|
||||
|
||||
it('should return empty array when only id is present', () => {
|
||||
const input = { id: '123' };
|
||||
|
||||
const result = getUpdatedFieldsFromRecordInput(input);
|
||||
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle inputs without id', () => {
|
||||
const input = { name: 'Bob', email: 'bob@test.com' };
|
||||
|
||||
const result = getUpdatedFieldsFromRecordInput(input);
|
||||
|
||||
expect(result).toEqual([{ name: 'Bob' }, { email: 'bob@test.com' }]);
|
||||
});
|
||||
|
||||
it('should handle empty input', () => {
|
||||
const result = getUpdatedFieldsFromRecordInput({});
|
||||
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
});
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { isSystemSearchVectorField } from '@/object-record/utils/isSystemSearchVectorField';
|
||||
|
||||
describe('isSystemSearchVectorField', () => {
|
||||
it('should return true for searchVector field', () => {
|
||||
expect(isSystemSearchVectorField('searchVector')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for other field names', () => {
|
||||
expect(isSystemSearchVectorField('name')).toBe(false);
|
||||
expect(isSystemSearchVectorField('id')).toBe(false);
|
||||
expect(isSystemSearchVectorField('position')).toBe(false);
|
||||
expect(isSystemSearchVectorField('')).toBe(false);
|
||||
});
|
||||
});
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import { sortRecordsByPosition } from '@/object-record/utils/sortRecordsByPosition';
|
||||
|
||||
describe('sortRecordsByPosition', () => {
|
||||
it('should sort by numeric position', () => {
|
||||
const record1 = { id: '1', __typename: 'Record', position: 1 };
|
||||
const record2 = { id: '2', __typename: 'Record', position: 2 };
|
||||
|
||||
expect(sortRecordsByPosition(record1, record2)).toBeLessThan(0);
|
||||
expect(sortRecordsByPosition(record2, record1)).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should return 0 for equal numeric positions', () => {
|
||||
const record1 = { id: '1', __typename: 'Record', position: 5 };
|
||||
const record2 = { id: '2', __typename: 'Record', position: 5 };
|
||||
|
||||
expect(sortRecordsByPosition(record1, record2)).toBe(0);
|
||||
});
|
||||
|
||||
it('should place "first" before other positions', () => {
|
||||
const record1 = { id: '1', __typename: 'Record', position: 'first' };
|
||||
const record2 = { id: '2', __typename: 'Record', position: 'last' };
|
||||
|
||||
expect(sortRecordsByPosition(record1 as any, record2 as any)).toBe(-1);
|
||||
});
|
||||
|
||||
it('should place "last" after other positions', () => {
|
||||
const record1 = { id: '1', __typename: 'Record', position: 'last' };
|
||||
const record2 = { id: '2', __typename: 'Record', position: 'first' };
|
||||
|
||||
expect(sortRecordsByPosition(record1 as any, record2 as any)).toBe(1);
|
||||
});
|
||||
|
||||
it('should return 0 for unknown position types', () => {
|
||||
const record1 = {
|
||||
id: '1',
|
||||
__typename: 'Record',
|
||||
position: undefined as any,
|
||||
};
|
||||
const record2 = {
|
||||
id: '2',
|
||||
__typename: 'Record',
|
||||
position: undefined as any,
|
||||
};
|
||||
|
||||
expect(sortRecordsByPosition(record1, record2)).toBe(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user