InspectorRAGet / src /__tests__ /objects.test.ts
kpfadnis's picture
feat: add ModelCharacteristics view and fix BFCL converter data quality
2542139
raw
history blame
7.53 kB
/**
*
* Copyright 2023-present InspectorRAGet Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**/
import { describe, it, expect } from 'vitest';
import {
camelCaseKeys,
snakeCaseKeys,
areObjectsIntersecting,
} from '@/src/utilities/objects';
// --- camelCaseKeys ---
describe('camelCaseKeys', () => {
it('converts default snake_case keys to camelCase', () => {
const input = { task_id: '1', model_id: 'm1', other_key: 'keep' };
const result = camelCaseKeys(input);
expect(result).toEqual({ taskId: '1', modelId: 'm1', other_key: 'keep' });
});
it('leaves non-listed keys untouched', () => {
const input = { foo_bar: 'value', task_id: 'x' };
const result = camelCaseKeys(input);
expect(result).toHaveProperty('foo_bar', 'value');
expect(result).toHaveProperty('taskId', 'x');
});
it('handles nested objects recursively', () => {
const input = { task_id: '1', nested: { model_id: 'm1' } };
const result = camelCaseKeys(input);
expect(result).toEqual({ taskId: '1', nested: { modelId: 'm1' } });
});
it('handles arrays of objects', () => {
const input = [{ task_id: '1' }, { task_id: '2' }];
const result = camelCaseKeys(input as any);
expect(result).toEqual([{ taskId: '1' }, { taskId: '2' }]);
});
it('returns primitives unchanged', () => {
expect(camelCaseKeys('hello' as any)).toBe('hello');
expect(camelCaseKeys(42 as any)).toBe(42);
expect(camelCaseKeys(null as any)).toBeNull();
});
it('uses custom keys list when provided', () => {
const input = { foo_bar: 'val', task_id: 'keep' };
const result = camelCaseKeys(input, ['foo_bar']);
expect(result).toHaveProperty('fooBar', 'val');
expect(result).toHaveProperty('task_id', 'keep');
});
it('handles empty objects', () => {
expect(camelCaseKeys({})).toEqual({});
});
it('handles empty arrays', () => {
expect(camelCaseKeys([] as any)).toEqual([]);
});
it('does not recurse into labels — snake_case label keys pass through unchanged', () => {
const input = {
task_id: 't1',
labels: { error_type: 'force_terminated', response_language: 'fr' },
};
const result = camelCaseKeys(input);
expect(result).toEqual({
taskId: 't1',
labels: { error_type: 'force_terminated', response_language: 'fr' },
});
});
it('does not recurse into labels when the value is null', () => {
const input = { task_id: 't1', labels: { error_type: null } };
const result = camelCaseKeys(input);
expect(result).toEqual({ taskId: 't1', labels: { error_type: null } });
});
it('converts all default keys', () => {
const input = {
task_id: 'a',
model_id: 'b',
depends_on: 'c',
display_value: 'd',
numeric_value: 'e',
min_value: 'f',
max_value: 'g',
task_type: 'h',
num_tasks: 'i',
start_timestamp: 'j',
end_timestamp: 'k',
document_id: 'l',
display_name: 'm',
};
const result = camelCaseKeys(input);
expect(result).toEqual({
taskId: 'a',
modelId: 'b',
dependsOn: 'c',
displayValue: 'd',
numericValue: 'e',
minValue: 'f',
maxValue: 'g',
taskType: 'h',
numTasks: 'i',
startTimestamp: 'j',
endTimestamp: 'k',
documentId: 'l',
displayName: 'm',
});
});
});
// --- snakeCaseKeys ---
describe('snakeCaseKeys', () => {
it('converts default camelCase keys to snake_case', () => {
const input = { taskId: '1', modelId: 'm1', otherKey: 'keep' };
const result = snakeCaseKeys(input);
expect(result).toEqual({ task_id: '1', model_id: 'm1', otherKey: 'keep' });
});
it('handles nested objects recursively', () => {
const input = { taskId: '1', nested: { modelId: 'm1' } };
const result = snakeCaseKeys(input);
expect(result).toEqual({ task_id: '1', nested: { model_id: 'm1' } });
});
it('handles arrays of objects', () => {
const input = [{ taskId: '1' }, { taskId: '2' }];
const result = snakeCaseKeys(input as any);
expect(result).toEqual([{ task_id: '1' }, { task_id: '2' }]);
});
it('returns primitives unchanged', () => {
expect(snakeCaseKeys('hello' as any)).toBe('hello');
expect(snakeCaseKeys(42 as any)).toBe(42);
});
it('uses custom keys list when provided', () => {
const input = { fooBar: 'val', taskId: 'keep' };
const result = snakeCaseKeys(input, ['fooBar']);
expect(result).toHaveProperty('foo_bar', 'val');
expect(result).toHaveProperty('taskId', 'keep');
});
it('does not recurse into labels — label keys pass through unchanged on export round-trip', () => {
const input = {
taskId: 't1',
labels: { error_type: 'ast_decoder:decoder_failed' },
};
const result = snakeCaseKeys(input);
expect(result).toEqual({
task_id: 't1',
labels: { error_type: 'ast_decoder:decoder_failed' },
});
});
});
// --- areObjectsIntersecting ---
describe('areObjectsIntersecting', () => {
it('returns true when objects share a key-value pair', () => {
const a = { color: 'red' };
const b = { color: 'red' };
expect(areObjectsIntersecting(a, b)).toBe(true);
});
it('returns false when values differ for same key', () => {
const a = { color: 'red' };
const b = { color: 'blue' };
expect(areObjectsIntersecting(a, b)).toBe(false);
});
it('treats "all" as matching any value', () => {
const a = { color: 'all' };
const b = { color: 'red' };
expect(areObjectsIntersecting(a, b)).toBe(true);
});
it('"all" matches even when key is missing from b', () => {
const a = { color: 'all' };
const b = { size: 'large' };
expect(areObjectsIntersecting(a, b)).toBe(true);
});
it('returns false when a has a non-empty value but key is missing in b', () => {
const a = { color: 'red' };
const b = { size: 'large' };
expect(areObjectsIntersecting(a, b)).toBe(false);
});
it('handles array values with intersection', () => {
const a = { color: ['red', 'blue'] };
const b = { color: ['blue', 'green'] };
expect(areObjectsIntersecting(a, b)).toBe(true);
});
it('handles array values without intersection', () => {
const a = { color: ['red', 'blue'] };
const b = { color: ['green', 'yellow'] };
expect(areObjectsIntersecting(a, b)).toBe(false);
});
it('requires all keys in a to intersect (AND logic)', () => {
const a = { color: 'red', size: 'large' };
const b = { color: 'red', size: 'small' };
expect(areObjectsIntersecting(a, b)).toBe(false);
});
it('returns true when all keys in a intersect with b', () => {
const a = { color: 'red', size: 'large' };
const b = { color: 'red', size: 'large' };
expect(areObjectsIntersecting(a, b)).toBe(true);
});
it('returns false when a has non-empty value and b value is empty', () => {
const a = { color: 'red' };
const b = { color: '' };
expect(areObjectsIntersecting(a, b)).toBe(false);
});
});