import { FieldValueTypes, OperatorTypes, Semantics } from '@unito/integration-api'; import assert from 'node:assert/strict'; import { describe, it } from 'node:test'; import { buildCollectionQueryParams, getApplicableFilters } from '../src/helpers.js'; describe('Helpers', () => { describe('getApplicableFilters', () => { it('returns only filters for defined fields', () => { const actual = getApplicableFilters( { filters: [ { field: 'status', operator: OperatorTypes.EQUAL, values: ['active', 'pending'] }, { field: 'email', operator: OperatorTypes.IS_NOT_NULL, values: [] }, ], }, [ { name: 'status', label: 'Status', type: FieldValueTypes.STRING, }, ], ); const expected = [{ field: 'status', operator: OperatorTypes.EQUAL, values: ['active', 'pending'] }]; assert.deepEqual(actual, expected); }); it('translates semantics into field names', () => { const actual = getApplicableFilters( { filters: [ { field: 'semantic:displayName', operator: OperatorTypes.START_WITH, values: ['Bob'] }, { field: 'semantic:createdAt', operator: OperatorTypes.EQUAL, values: ['2021-01-01'] }, ], }, [ { name: 'name', label: 'Name', type: FieldValueTypes.STRING, semantic: Semantics.DISPLAY_NAME, }, ], ); const expected = [{ field: 'name', operator: OperatorTypes.START_WITH, values: ['Bob'] }]; assert.deepEqual(actual, expected); }); it('gracefully handle garbage', () => { const actual = getApplicableFilters( { filters: [ { field: '...', operator: OperatorTypes.EQUAL, values: [] }, { field: ':', operator: OperatorTypes.EQUAL, values: [] }, { field: '', operator: OperatorTypes.EQUAL, values: [] }, ], }, [ { name: 'status', label: 'Status', type: FieldValueTypes.STRING, }, ], ); assert.deepEqual(actual, []); }); }); describe('buildCollectionQueryParams', () => { it('encodes a single filter with one value', () => { const result = buildCollectionQueryParams({ filters: [{ field: 'status', operator: OperatorTypes.EQUAL, values: ['active'] }], }); assert.equal(result.get('filter'), 'status=active'); assert.equal(result.get('select'), null); }); it('encodes filter values with special characters', () => { const result = buildCollectionQueryParams({ filters: [{ field: 'status', operator: OperatorTypes.EQUAL, values: ['foo,bar'] }], }); assert.equal(result.get('filter'), 'status=foo%2Cbar'); }); it('encodes filter values containing pipe characters', () => { const result = buildCollectionQueryParams({ filters: [{ field: 'tags', operator: OperatorTypes.EQUAL, values: ['a|b'] }], }); assert.equal(result.get('filter'), 'tags=a%7Cb'); }); it('joins multiple values for one filter with |', () => { const result = buildCollectionQueryParams({ filters: [{ field: 'status', operator: OperatorTypes.EQUAL, values: ['active', 'pending'] }], }); assert.equal(result.get('filter'), 'status=active|pending'); }); it('joins multiple filters with ,', () => { const result = buildCollectionQueryParams({ filters: [ { field: 'status', operator: OperatorTypes.EQUAL, values: ['active'] }, { field: 'name', operator: OperatorTypes.INCLUDE, values: ['john'] }, ], }); assert.equal(result.get('filter'), 'status=active,name*=john'); }); it('handles IS_NULL operator (no values)', () => { const result = buildCollectionQueryParams({ filters: [{ field: 'status', operator: OperatorTypes.IS_NULL, values: [] }], }); assert.equal(result.get('filter'), 'status!!'); }); it('handles IS_NULL operator with undefined values', () => { const result = buildCollectionQueryParams({ filters: [{ field: 'status', operator: OperatorTypes.IS_NULL, values: undefined }], }); assert.equal(result.get('filter'), 'status!!'); }); it('handles IS_NOT_NULL operator (no values)', () => { const result = buildCollectionQueryParams({ filters: [{ field: 'assignee', operator: OperatorTypes.IS_NOT_NULL, values: [] }], }); assert.equal(result.get('filter'), 'assignee!'); }); it('encodes selects', () => { const result = buildCollectionQueryParams({ selects: ['name', 'dept.id'], }); assert.equal(result.get('select'), 'name,dept.id'); assert.equal(result.get('filter'), null); }); it('encodes selects with special characters', () => { const result = buildCollectionQueryParams({ selects: ['field with spaces'], }); assert.equal(result.get('select'), 'field%20with%20spaces'); }); it('encodes both filters and selects', () => { const result = buildCollectionQueryParams({ filters: [{ field: 'status', operator: OperatorTypes.EQUAL, values: ['active'] }], selects: ['name', 'status'], }); assert.equal(result.get('filter'), 'status=active'); assert.equal(result.get('select'), 'name,status'); }); it('returns empty URLSearchParams when called with no arguments', () => { const result = buildCollectionQueryParams(); assert.equal(result.toString(), ''); }); it('omits filter key for empty filters array', () => { const result = buildCollectionQueryParams({ filters: [] }); assert.equal(result.get('filter'), null); }); it('omits select key for empty selects array', () => { const result = buildCollectionQueryParams({ selects: [] }); assert.equal(result.get('select'), null); }); it('can be extended with additional params (e.g. cursor)', () => { const result = buildCollectionQueryParams({ selects: ['name'], }); result.append('cursor', 'abc123'); assert.equal(result.toString(), 'select=name&cursor=abc123'); }); }); });