Skip to main content
Glama
vizqlDataServiceApi.test.ts21.2 kB
import { Field, Filter } from './vizqlDataServiceApi.js'; describe('Field schema', () => { it('accepts a minimal valid Field', () => { const data = { fieldCaption: 'Sales' }; expect(() => Field.parse(data)).not.toThrow(); }); it('accepts a Field with a function', () => { const data = { fieldCaption: 'Profit', function: 'SUM' }; expect(() => Field.parse(data)).not.toThrow(); }); it('accepts a Field with a calculation', () => { const data = { fieldCaption: 'Profit', calculation: 'SUM([Profit])' }; expect(() => Field.parse(data)).not.toThrow(); }); it('rejects a Field missing fieldCaption', () => { const data = { function: 'SUM' }; expect(() => Field.parse(data)).toThrow(); }); it('rejects a Field with extra properties (strict mode)', () => { const data = { fieldCaption: 'Sales', extra: 123 }; expect(() => Field.parse(data)).toThrow(); }); it('rejects a Field with both function and calculation', () => { const data = { fieldCaption: 'Profit', function: 'SUM', calculation: 'SUM([Profit])' }; expect(() => Field.parse(data)).toThrow(); }); }); describe('SET Filter schema', () => { it('accepts a valid SET filter', () => { const data = { filterType: 'SET', field: { fieldCaption: 'Category' }, values: ['Technology', 'Furniture'], }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid SET filter that excludes values', () => { const data = { filterType: 'SET', field: { fieldCaption: 'Category' }, values: ['Technology', 'Furniture'], exclude: true, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a SET filter with a function', () => { const data = { filterType: 'SET', field: { fieldCaption: 'Category', function: 'SUM' }, values: ['Technology', 'Furniture'], }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a SET filter with a calculation', () => { const data = { filterType: 'SET', field: { fieldCaption: 'Category', calculation: 'SUM([Sales])' }, values: ['Technology', 'Furniture'], }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a SET filter with no values', () => { const data = { filterType: 'SET', field: { fieldCaption: 'Category' }, exclude: true, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a SET filter with extra properties (strict mode)', () => { const data = { filterType: 'SET', field: { fieldCaption: 'Category' }, values: ['A', 'B'], extra: 123, }; expect(() => Filter.parse(data)).toThrow(); }); }); describe('TOP N Filter schema', () => { it('accepts a valid TOP N filter', () => { const data = { filterType: 'TOP', field: { fieldCaption: 'State' }, howMany: 5, fieldToMeasure: { fieldCaption: 'Sales', function: 'SUM' }, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid TOP N filter with a calculation', () => { const data = { filterType: 'TOP', field: { fieldCaption: 'State' }, howMany: 10, fieldToMeasure: { calculation: 'SUM([Revenue]) - SUM([Cost])' }, direction: 'BOTTOM', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid TOP N filter with a function', () => { const data = { filterType: 'TOP', field: { calculation: 'MONTH([Order Date])' }, howMany: 10, fieldToMeasure: { fieldCaption: 'Sales', function: 'SUM' }, direction: 'BOTTOM', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a TOP N filter with no fieldToMeasure', () => { const data = { filterType: 'TOP', field: { fieldCaption: 'State' }, howMany: 5, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a TOP N filter with no howMany', () => { const data = { filterType: 'TOP', field: { fieldCaption: 'State' }, fieldToMeasure: { fieldCaption: 'Sales', function: 'SUM' }, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a TOP N filter with no field', () => { const data = { filterType: 'TOP', howMany: 5, fieldToMeasure: { fieldCaption: 'Sales', function: 'SUM' }, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a TOP N filter with extra properties (strict mode)', () => { const data = { filterType: 'TOP', field: { fieldCaption: 'State' }, howMany: 5, fieldToMeasure: { fieldCaption: 'Profit', function: 'SUM' }, extra: 123, }; expect(() => Filter.parse(data)).toThrow(); }); }); describe('MATCH Filter schema', () => { it('accepts a valid MATCH filter (contains)', () => { const data = { filterType: 'MATCH', field: { fieldCaption: 'Product Name' }, contains: 'Desk', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid MATCH filter (startsWith)', () => { const data = { filterType: 'MATCH', field: { fieldCaption: 'Product Name' }, startsWith: 'Desk', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid MATCH filter (endsWith)', () => { const data = { filterType: 'MATCH', field: { fieldCaption: 'Product Name' }, endsWith: 'Chair', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid MATCH filter with startsWith, endsWith, and contains', () => { const data = { filterType: 'MATCH', field: { fieldCaption: 'Product Name' }, startsWith: 'Desk', endsWith: 'Chair', contains: 'Office', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a MATCH filter with none of startsWith, endsWith, or contains', () => { const data = { filterType: 'MATCH', field: { fieldCaption: 'Product Name' }, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a MATCH filter if the field has a function', () => { const data = { filterType: 'MATCH', field: { fieldCaption: 'Product Name', function: 'SUM' }, contains: 'Desk', }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a MATCH filter if the field has a calculation', () => { const data = { filterType: 'MATCH', field: { fieldCaption: 'Product Name', calculation: 'SUM([Sales])' }, contains: 'Desk', }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a MATCH filter with extra properties (strict mode)', () => { const data = { filterType: 'MATCH', field: { fieldCaption: 'Product Name' }, contains: 'Desk', extra: 123, }; expect(() => Filter.parse(data)).toThrow(); }); }); describe('QUANTITATIVE_NUMERICAL Filter schema', () => { it('accepts a valid QUANTITATIVE_NUMERICAL filter (RANGE)', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'RANGE', field: { fieldCaption: 'Sales' }, min: 100, max: 1000, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid QUANTITATIVE_NUMERICAL filter (RANGE) which includes nulls', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'RANGE', field: { fieldCaption: 'Sales' }, min: 100, max: 1000, includeNulls: true, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a QUANTITATIVE_NUMERICAL filter (RANGE) if missing min', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'RANGE', field: { fieldCaption: 'Sales' }, max: 1000, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a QUANTITATIVE_NUMERICAL filter (RANGE) if missing max', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'RANGE', field: { fieldCaption: 'Sales' }, min: 100, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a QUANTITATIVE_NUMERICAL filter (RANGE) if missing min and max', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'RANGE', field: { fieldCaption: 'Sales' }, }; expect(() => Filter.parse(data)).toThrow(); }); it('accepts a valid QUANTITATIVE_NUMERICAL filter (MIN)', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'MIN', field: { fieldCaption: 'Sales' }, min: 100, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid QUANTITATIVE_NUMERICAL filter (MIN) which includes nulls', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'MIN', field: { fieldCaption: 'Sales' }, min: 100, includeNulls: true, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a QUANTITATIVE_NUMERICAL filter (MIN) if missing min', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'MIN', field: { fieldCaption: 'Sales' }, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a QUANTITATIVE_NUMERICAL filter (MIN) which includes max', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'MIN', field: { fieldCaption: 'Sales' }, min: 100, max: 1000, }; expect(() => Filter.parse(data)).toThrow(); }); it('accepts a valid QUANTITATIVE_NUMERICAL filter (MAX)', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'MAX', field: { fieldCaption: 'Sales' }, max: 1000, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid QUANTITATIVE_NUMERICAL filter (MAX) which includes nulls', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'MAX', field: { fieldCaption: 'Sales' }, max: 1000, includeNulls: true, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a QUANTITATIVE_NUMERICAL filter (MAX) if missing max', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'MAX', field: { fieldCaption: 'Sales' }, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a QUANTITATIVE_NUMERICAL filter (MAX) which includes min', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'MIN', field: { fieldCaption: 'Sales' }, min: 100, max: 1000, }; expect(() => Filter.parse(data)).toThrow(); }); it('accepts a valid QUANTITATIVE_NUMERICAL filter (ONLY_NULL)', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'ONLY_NULL', field: { fieldCaption: 'Sales' }, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a QUANTITATIVE_NUMERICAL filter (ONLY_NULL) if it uses includeNulls', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'ONLY_NULL', field: { fieldCaption: 'Sales' }, includeNulls: true, }; expect(() => Filter.parse(data)).toThrow(); }); it('accepts a valid QUANTITATIVE_NUMERICAL filter (ONLY_NON_NULL)', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'ONLY_NON_NULL', field: { fieldCaption: 'Sales' }, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a QUANTITATIVE_NUMERICAL filter (ONLY_NON_NULL) if it uses includeNulls', () => { const data = { filterType: 'QUANTITATIVE_NUMERICAL', quantitativeFilterType: 'ONLY_NON_NULL', field: { fieldCaption: 'Sales' }, includeNulls: false, }; expect(() => Filter.parse(data)).toThrow(); }); }); describe('QUANTITATIVE_DATE Filter schema', () => { it('accepts a valid QUANTITATIVE_DATE filter (RANGE)', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'RANGE', field: { fieldCaption: 'Order Date' }, minDate: '2023-01-01', maxDate: '2023-12-31', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid QUANTITATIVE_DATE filter (RANGE) with includeNulls', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'RANGE', field: { fieldCaption: 'Order Date' }, minDate: '2023-01-01', maxDate: '2023-12-31', includeNulls: true, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a QUANTITATIVE_DATE filter (RANGE) missing minDate', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'RANGE', field: { fieldCaption: 'Order Date' }, maxDate: '2023-12-31', }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a QUANTITATIVE_DATE filter (RANGE) missing maxDate', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'RANGE', field: { fieldCaption: 'Order Date' }, minDate: '2023-01-01', }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a QUANTITATIVE_DATE filter (RANGE) missing minDate and maxDate', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'RANGE', field: { fieldCaption: 'Order Date' }, }; expect(() => Filter.parse(data)).toThrow(); }); it('accepts a valid QUANTITATIVE_DATE filter (MIN)', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'MIN', field: { fieldCaption: 'Order Date' }, minDate: '2023-01-01', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid QUANTITATIVE_DATE filter (MIN) which includes nulls', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'MIN', field: { fieldCaption: 'Order Date' }, minDate: '2023-01-01', includeNulls: true, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a QUANTITATIVE_DATE filter (MIN) missing minDate', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'MIN', field: { fieldCaption: 'Order Date' }, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a QUANTITATIVE_DATE filter (MIN) which includes max', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'MIN', field: { fieldCaption: 'Order Date' }, minDate: '2023-01-01', maxDate: '2023-12-31', }; expect(() => Filter.parse(data)).toThrow(); }); it('accepts a valid QUANTITATIVE_DATE filter (MAX)', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'MAX', field: { fieldCaption: 'Order Date' }, maxDate: '2023-12-31', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid QUANTITATIVE_DATE filter (MAX) which includes nulls', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'MAX', field: { fieldCaption: 'Order Date' }, maxDate: '2023-12-31', includeNulls: true, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a QUANTITATIVE_DATE filter (MAX) missing maxDate', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'MAX', field: { fieldCaption: 'Order Date' }, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a QUANTITATIVE_DATE filter (MAX) which includes min', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'MAX', field: { fieldCaption: 'Order Date' }, minDate: '2023-01-01', maxDate: '2023-12-31', }; expect(() => Filter.parse(data)).toThrow(); }); it('accepts a valid QUANTITATIVE_DATE filter (ONLY_NULL)', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'ONLY_NULL', field: { fieldCaption: 'Order Date' }, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects an QUANTITATIVE_DATE filter (ONLY_NULL) with includeNulls', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'ONLY_NULL', field: { fieldCaption: 'Order Date' }, includeNulls: true, }; expect(() => Filter.parse(data)).toThrow(); }); it('accepts a valid QUANTITATIVE_DATE filter (ONLY_NON_NULL)', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'ONLY_NON_NULL', field: { fieldCaption: 'Order Date' }, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects an QUANTITATIVE_DATE filter (ONLY_NON_NULL) with includeNulls', () => { const data = { filterType: 'QUANTITATIVE_DATE', quantitativeFilterType: 'ONLY_NON_NULL', field: { fieldCaption: 'Order Date' }, includeNulls: false, }; expect(() => Filter.parse(data)).toThrow(); }); }); describe('DATE Filter schema', () => { it('accepts a valid DATE filter (CURRENT)', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date' }, periodType: 'YEARS', dateRangeType: 'CURRENT', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid DATE filter (LAST)', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date' }, periodType: 'MONTHS', dateRangeType: 'LAST', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid DATE filter (NEXT)', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date' }, periodType: 'MONTHS', dateRangeType: 'NEXT', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid DATE filter (TODATE)', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date' }, periodType: 'DAYS', dateRangeType: 'TODATE', anchorDate: '2025-01-01', }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid DATE filter (LASTN)', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date' }, periodType: 'MONTHS', dateRangeType: 'LASTN', rangeN: 3, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('accepts a valid DATE filter (NEXTN)', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date' }, periodType: 'MONTHS', dateRangeType: 'NEXTN', rangeN: 2, }; expect(() => Filter.parse(data)).not.toThrow(); }); it('rejects a DATE filter missing periodType', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date' }, dateRangeType: 'CURRENT', }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a DATE filter (TODATE) missing dateRangeType', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date' }, periodType: 'DAYS', }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a DATE filter (LASTN) missing rangeN', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date' }, periodType: 'MONTHS', dateRangeType: 'LASTN', }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a DATE filter (NEXTN) missing rangeN', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date' }, periodType: 'MONTHS', dateRangeType: 'NEXTN', }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a DATE filter with rangeN (not NEXTN or LASTN)', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date' }, periodType: 'MONTHS', dateRangeType: 'CURRENT', rangeN: 1, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a DATE filter with function', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date', function: 'SUM' }, periodType: 'MONTHS', dateRangeType: 'NEXT', rangeN: 1, }; expect(() => Filter.parse(data)).toThrow(); }); it('rejects a DATE filter with calculation', () => { const data = { filterType: 'DATE', field: { fieldCaption: 'Order Date', calculation: 'SUM([Sales])' }, periodType: 'MONTHS', dateRangeType: 'NEXT', rangeN: 1, }; expect(() => Filter.parse(data)).toThrow(); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/datalabs89/tableau-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server