"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const moment_1 = tslib_1.__importDefault(require("moment/moment"));
const filter_1 = require("../types/filter");
const timeFrames_1 = require("../utils/timeFrames");
const filtersCompiler_1 = require("./filtersCompiler");
const filtersCompiler_mock_1 = require("./filtersCompiler.mock");
const formatTimestamp = (date) => (0, moment_1.default)(date).format('YYYY-MM-DD HH:mm:ss');
describe('Filter SQL', () => {
    beforeAll(() => {
        jest.useFakeTimers();
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
    });
    afterAll(() => {
        jest.useFakeTimers();
    });
    test.each(Object.values(filter_1.FilterOperator))('should return number filter sql for operator %s', (operator) => {
        if (!filtersCompiler_mock_1.ExpectedNumberFilterSQL[operator]) {
            expect(() => {
                (0, filtersCompiler_1.renderNumberFilterSql)(filtersCompiler_mock_1.NumberDimensionMock, {
                    ...filtersCompiler_mock_1.NumberFilterBase,
                    operator,
                });
            }).toThrow();
            return;
        }
        if (filtersCompiler_mock_1.NumberOperatorsWithMultipleValues.includes(operator)) {
            expect((0, filtersCompiler_1.renderNumberFilterSql)(filtersCompiler_mock_1.NumberDimensionMock, {
                ...filtersCompiler_mock_1.NumberFilterBaseWithMultiValues,
                operator,
            })).toStrictEqual(filtersCompiler_mock_1.ExpectedNumberFilterSQL[operator]);
            return;
        }
        expect((0, filtersCompiler_1.renderNumberFilterSql)(filtersCompiler_mock_1.NumberDimensionMock, {
            ...filtersCompiler_mock_1.NumberFilterBase,
            operator,
        })).toStrictEqual(filtersCompiler_mock_1.ExpectedNumberFilterSQL[operator]);
    });
    test.each(Object.values(filter_1.UnitOfTime))('should return in the current %s filter sql', (unitOfTime) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, {
            ...filtersCompiler_mock_1.InTheCurrentFilterBase,
            settings: { unitOfTime },
        }, filtersCompiler_mock_1.adapterType.default, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.ExpectedInTheCurrentFilterSQL[unitOfTime]);
    });
    test.each(Object.values(filter_1.UnitOfTime))('should return in the current %s filter sql for trino adapter', (unitOfTime) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, {
            ...filtersCompiler_mock_1.InTheCurrentFilterBase,
            settings: { unitOfTime },
        }, filtersCompiler_mock_1.adapterType.trino, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.TrinoExpectedInTheCurrentFilterSQL[unitOfTime]);
    });
    test.each(Object.values(filter_1.UnitOfTime))('should return in the next %s filter sql', (unitOfTime) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, {
            ...filtersCompiler_mock_1.InTheNextFilterBase,
            settings: { unitOfTime },
        }, filtersCompiler_mock_1.adapterType.default, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.ExpectedInTheNextFilterSQL[unitOfTime]);
    });
    test.each(Object.values(filter_1.UnitOfTime))('should return in the next %s filter sql for trino adapter', (unitOfTime) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, {
            ...filtersCompiler_mock_1.InTheNextFilterBase,
            settings: { unitOfTime },
        }, filtersCompiler_mock_1.adapterType.trino, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.TrinoExpectedInTheNextFilterSQL[unitOfTime]);
    });
    test.each(Object.values(filter_1.UnitOfTime))('should return in the next complete %s filter sql', (unitOfTime) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, {
            ...filtersCompiler_mock_1.InTheNextFilterBase,
            settings: { unitOfTime, completed: true },
        }, filtersCompiler_mock_1.adapterType.default, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.ExpectedInTheNextCompleteFilterSQL[unitOfTime]);
    });
    test.each(Object.values(filter_1.UnitOfTime))('should return in the next complete %s filter sql for trino adapter', (unitOfTime) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, {
            ...filtersCompiler_mock_1.InTheNextFilterBase,
            settings: { unitOfTime, completed: true },
        }, filtersCompiler_mock_1.adapterType.trino, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.TrinoExpectedInTheNextCompleteFilterSQL[unitOfTime]);
    });
    test.each([timeFrames_1.WeekDay.MONDAY, timeFrames_1.WeekDay.SUNDAY])('should return in the next complete week filter sql with %s as the start of the week', (weekDay) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        const filter = {
            ...filtersCompiler_mock_1.InTheNextFilterBase,
            settings: { unitOfTime: filter_1.UnitOfTime.weeks, completed: true },
        };
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filter, filtersCompiler_mock_1.adapterType.default, 'UTC', formatTimestamp, weekDay)).toStrictEqual(filtersCompiler_mock_1.ExpectedInTheNextCompleteWeekFilterSQLWithCustomStartOfWeek[weekDay]);
    });
    test.each([timeFrames_1.WeekDay.MONDAY, timeFrames_1.WeekDay.SUNDAY])('should return in the next complete week filter sql with %s as the start of the week for trino adapter', (weekDay) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        const filter = {
            ...filtersCompiler_mock_1.InTheNextFilterBase,
            settings: { unitOfTime: filter_1.UnitOfTime.weeks, completed: true },
        };
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filter, filtersCompiler_mock_1.adapterType.trino, 'UTC', formatTimestamp, weekDay)).toStrictEqual(filtersCompiler_mock_1.TrinoExpectedInTheNextCompleteWeekFilterSQLWithCustomStartOfWeek[weekDay]);
    });
    test.each([timeFrames_1.WeekDay.MONDAY, timeFrames_1.WeekDay.SUNDAY])('should return in the last complete week filter sql with %s as the start of the week', (weekDay) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        const filter = {
            ...filtersCompiler_mock_1.InThePastFilterBase,
            settings: { unitOfTime: filter_1.UnitOfTime.weeks, completed: true },
        };
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filter, filtersCompiler_mock_1.adapterType.default, 'UTC', formatTimestamp, weekDay)).toStrictEqual(filtersCompiler_mock_1.ExpectedInThePastCompleteWeekFilterSQLWithCustomStartOfWeek[weekDay]);
    });
    test.each([timeFrames_1.WeekDay.MONDAY, timeFrames_1.WeekDay.SUNDAY])('should return in the last complete week filter sql with %s as the start of the week for trino adapter', (weekDay) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        const filter = {
            ...filtersCompiler_mock_1.InThePastFilterBase,
            settings: { unitOfTime: filter_1.UnitOfTime.weeks, completed: true },
        };
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filter, filtersCompiler_mock_1.adapterType.trino, 'UTC', formatTimestamp, weekDay)).toStrictEqual(filtersCompiler_mock_1.TrinoExpectedInThePastCompleteWeekFilterSQLWithCustomStartOfWeek[weekDay]);
    });
    test.each([timeFrames_1.WeekDay.MONDAY, timeFrames_1.WeekDay.SUNDAY])('should return in the current complete week filter sql with %s as the start of the week', (weekDay) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        const filter = {
            ...filtersCompiler_mock_1.InTheCurrentFilterBase,
            settings: { unitOfTime: filter_1.UnitOfTime.weeks, completed: true },
        };
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filter, filtersCompiler_mock_1.adapterType.default, 'UTC', formatTimestamp, weekDay)).toStrictEqual(filtersCompiler_mock_1.ExpectedInTheCurrentWeekFilterSQLWithCustomStartOfWeek[weekDay]);
    });
    test.each([timeFrames_1.WeekDay.MONDAY, timeFrames_1.WeekDay.SUNDAY])('should return in the current complete week filter sql with %s as the start of the week for trino adapter', (weekDay) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        const filter = {
            ...filtersCompiler_mock_1.InTheCurrentFilterBase,
            settings: { unitOfTime: filter_1.UnitOfTime.weeks, completed: true },
        };
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filter, filtersCompiler_mock_1.adapterType.trino, 'UTC', formatTimestamp, weekDay)).toStrictEqual(filtersCompiler_mock_1.TrinoExpectedInTheCurrentWeekFilterSQLWithCustomStartOfWeek[weekDay]);
    });
    test('should return in the last date filter sql', () => {
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1DayFilter, filtersCompiler_mock_1.adapterType.default, 'UTC')).toStrictEqual(filtersCompiler_mock_1.InTheLast1DayFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1WeekFilter, filtersCompiler_mock_1.adapterType.default, 'UTC')).toStrictEqual(filtersCompiler_mock_1.InTheLast1WeekFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1MonthFilter, filtersCompiler_mock_1.adapterType.default, 'UTC')).toStrictEqual(filtersCompiler_mock_1.InTheLast1MonthFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1YearFilter, filtersCompiler_mock_1.adapterType.default, 'UTC')).toStrictEqual(filtersCompiler_mock_1.InTheLast1YearFilterSQL);
    });
    test('should return in the last date filter sql for trino adapter', () => {
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1DayFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC')).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1DayFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1WeekFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC')).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1WeekFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1MonthFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC')).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1MonthFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1YearFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC')).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1YearFilterSQL);
    });
    test('should return in the last completed date filter sql ', () => {
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedDayFilter, filtersCompiler_mock_1.adapterType.default, 'UTC')).toStrictEqual(filtersCompiler_mock_1.InTheLast1CompletedDayFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedWeekFilter, filtersCompiler_mock_1.adapterType.default, 'UTC')).toStrictEqual(filtersCompiler_mock_1.InTheLast1CompletedWeekFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedMonthFilter, filtersCompiler_mock_1.adapterType.default, 'UTC')).toStrictEqual(filtersCompiler_mock_1.InTheLast1CompletedMonthFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedYearFilter, filtersCompiler_mock_1.adapterType.default, 'UTC')).toStrictEqual(filtersCompiler_mock_1.InTheLast1CompletedYearFilterSQL);
    });
    test('should return in the last completed date filter sql for trino adapter', () => {
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedDayFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC')).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1CompletedDayFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedWeekFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC')).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1CompletedWeekFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedMonthFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC')).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1CompletedMonthFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedYearFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC')).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1CompletedYearFilterSQL);
    });
    test('should return in the last date filter sql for timestamps', () => {
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1HourFilter, filtersCompiler_mock_1.adapterType.default, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.InTheLast1HourFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedHourFilter, filtersCompiler_mock_1.adapterType.default, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.InTheLast1CompletedHourFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1MinuteFilter, filtersCompiler_mock_1.adapterType.default, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.InTheLast1MinuteFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedMinuteFilter, filtersCompiler_mock_1.adapterType.default, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.InTheLast1CompletedMinuteFilterSQL);
    });
    test('should return in the last date filter sql for timestamps for trino adapter', () => {
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1HourFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1HourFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedHourFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1CompletedHourFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1MinuteFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1MinuteFilterSQL);
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheLast1CompletedMinuteFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.TrinoInTheLast1CompletedMinuteFilterSQL);
    });
    test('should return in between date filter sql', () => {
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InBetweenPastTwoYearsFilter, filtersCompiler_mock_1.adapterType.default, 'UTC')).toStrictEqual(filtersCompiler_mock_1.InBetweenPastTwoYearsFilterSQL);
    });
    test('should return in between date filter sql for trino adapter', () => {
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InBetweenPastTwoYearsFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC')).toStrictEqual(filtersCompiler_mock_1.TrinoInBetweenPastTwoYearsFilterSQL);
    });
    test('should return in between date filter sql for timestamps', () => {
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InBetweenPastTwoYearsFilter, filtersCompiler_mock_1.adapterType.default, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.InBetweenPastTwoYearsTimestampFilterSQL);
    });
    test('should return in between date filter sql for timestamps for trino adapter', () => {
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InBetweenPastTwoYearsFilter, filtersCompiler_mock_1.adapterType.trino, 'UTC', formatTimestamp)).toStrictEqual(filtersCompiler_mock_1.TrinoInBetweenPastTwoYearsTimestampFilterSQL);
    });
    test.each(filtersCompiler_mock_1.filterInTheCurrentDayTimezoneMocks)('should return in the current day filter sql for timezone %s', (timezone, expected) => {
        jest.setSystemTime(new Date('04 Apr 2020 06:12:30 GMT').getTime());
        expect((0, filtersCompiler_1.renderDateFilterSql)(filtersCompiler_mock_1.DimensionSqlMock, filtersCompiler_mock_1.InTheCurrentFilterBase, filtersCompiler_mock_1.adapterType.default, timezone, formatTimestamp)).toStrictEqual(expected);
    });
    test('should return single value in includes filter sql', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.includeFilterWithSingleVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.includeFilterWithSingleValSQL);
    });
    test('should return multiple values joined by OR in includes filter sql', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.includeFilterWithMultiVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.includeFilterWithMultiValSQL);
    });
    test('should return true in includes filter sql for empty filter', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.includeFilterWithNoVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.includeFilterWithNoValSQL);
    });
    test('should return single value in notIncludes filter sql', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.notIncludeFilterWithSingleVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.notIncludeFilterWithSingleValSQL);
    });
    test('should return multiple values joined by AND in notIncludes filter sql', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.notIncludeFilterWithMultiVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.notIncludeFilterWithMultiValSQL);
    });
    test('should return true in notIncludes filter sql for empty filter', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.notIncludeFilterWithNoVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.notIncludeFilterWithNoValSQL);
    });
    test('should return true when includes filter has empty string value', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.includeFilterWithEmptyString, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.includeFilterWithEmptyStringSQL);
    });
    test('should filter out empty strings and process valid values in mixed array', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.includeFilterWithMixedEmptyStrings, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.includeFilterWithMixedEmptyStringsSQL);
    });
    test('should return empty string filter sql when equals filter has empty string value', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.equalsFilterWithEmptyString, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.equalsFilterWithEmptyStringSQL);
    });
    test('should return true when starts with filter has empty string value', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.startsWithFilterWithEmptyString, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.startsWithFilterWithEmptyStringSQL);
    });
    test('should return true when ends with filter has empty string value', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.endsWithFilterWithEmptyString, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.endsWithFilterWithEmptyStringSQL);
    });
    test('should return true when not equals filter has empty string value', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.notEqualsFilterWithEmptyString, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.notEqualsFilterWithEmptyStringSQL);
    });
    test('should return true when not include filter has empty string value', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.notIncludeFilterWithEmptyString, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.notIncludeFilterWithEmptyStringSQL);
    });
    test('should return single value in startsWith filter sql', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.startsWithFilterWithSingleVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.startsWithFilterWithSingleValSQL);
    });
    test('should return multiple values joined by OR in startsWith filter sql', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.startsWithFilterWithMultiVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.startsWithFilterWithMultiValSQL);
    });
    test('should return true in startsWith filter sql for empty filter', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.startsWithFilterWithNoVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.startsWithFilterWithNoValSQL);
    });
    test('should return single value in endsWith filter sql', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.endsWithFilterWithSingleVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.endsWithFilterWithSingleValSQL);
    });
    test('should return multiple values joined by OR in endsWith filter sql', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.endsWithFilterWithMultiVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.endsWithFilterWithMultiValSQL);
    });
    test('should return true in endsWith filter sql for empty filter', () => {
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.endsWithFilterWithNoVal, "'")).toBe(filtersCompiler_mock_1.stringFilterRuleMocks.endsWithFilterWithNoValSQL);
    });
    test('should return 1=1 if filter is disabled', () => {
        expect((0, filtersCompiler_1.renderFilterRuleSqlFromField)(filtersCompiler_mock_1.disabledFilterMock.filterRule, filtersCompiler_mock_1.disabledFilterMock.field, filtersCompiler_mock_1.disabledFilterMock.fieldQuoteChar, filtersCompiler_mock_1.disabledFilterMock.stringQuoteChar, filtersCompiler_mock_1.disabledFilterMock.escapeString, filtersCompiler_mock_1.disabledFilterMock.startOfWeek, filtersCompiler_mock_1.disabledFilterMock.adapterType, filtersCompiler_mock_1.disabledFilterMock.timezone)).toBe('1=1');
    });
});
describe('escape string values', () => {
    test('should not escape on the string filter method', () => {
        // Escape happens now on the parent method, not on the string filter
        expect((0, filtersCompiler_1.renderStringFilterSql)(filtersCompiler_mock_1.stringFilterDimension, filtersCompiler_mock_1.stringFilterRuleMocks.equalsFilterWithSingleUnescapedValue, "'")).toBe(`("customers".first_name) IN ('Bob's')`);
    });
    test('should return escaped query for unescaped single filter value', () => {
        expect((0, filtersCompiler_1.renderFilterRuleSqlFromField)(filtersCompiler_mock_1.stringFilterRuleMocks.equalsFilterWithSingleUnescapedValue, filtersCompiler_mock_1.disabledFilterMock.field, filtersCompiler_mock_1.disabledFilterMock.fieldQuoteChar, filtersCompiler_mock_1.disabledFilterMock.stringQuoteChar, (v) => v.replaceAll("'", "''"), filtersCompiler_mock_1.disabledFilterMock.startOfWeek, filtersCompiler_mock_1.disabledFilterMock.adapterType, filtersCompiler_mock_1.disabledFilterMock.timezone)).toBe(`("payments".payment_method) IN ('Bob''s')`);
    });
    test('should return escaped query for unescaped multi filter values', () => {
        expect((0, filtersCompiler_1.renderFilterRuleSqlFromField)(filtersCompiler_mock_1.stringFilterRuleMocks.equalsFilterWithMultiUnescapedValue, filtersCompiler_mock_1.disabledFilterMock.field, filtersCompiler_mock_1.disabledFilterMock.fieldQuoteChar, filtersCompiler_mock_1.disabledFilterMock.stringQuoteChar, (v) => v.replaceAll("'", "''"), filtersCompiler_mock_1.disabledFilterMock.startOfWeek, filtersCompiler_mock_1.disabledFilterMock.adapterType, filtersCompiler_mock_1.disabledFilterMock.timezone)).toBe(`("payments".payment_method) IN ('Bob''s','Tom''s')`);
    });
});
describe('Boolean Filter SQL', () => {
    const dimensionSql = '("table"."is_active")';
    const baseFilter = {
        id: 'test-id',
        target: { fieldId: 'is_active' },
    };
    describe('equals operator', () => {
        it('should handle boolean true correctly', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: [true],
            };
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filter)).toBe('(("table"."is_active")) = true');
        });
        it('should handle boolean false correctly', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: [false],
            };
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filter)).toBe('(("table"."is_active")) = false');
        });
        it('should handle string "true" correctly', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: ['true'],
            };
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filter)).toBe('(("table"."is_active")) = true');
        });
        it('should handle string "false" correctly (THIS WILL FAIL BEFORE FIX)', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: ['false'],
            };
            // This test will fail initially because current implementation returns "true"
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filter)).toBe('(("table"."is_active")) = false');
        });
        it('should handle case insensitive string booleans', () => {
            const filterFalse = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: ['FALSE'],
            };
            const filterTrue = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: ['TRUE'],
            };
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filterFalse)).toBe('(("table"."is_active")) = false');
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filterTrue)).toBe('(("table"."is_active")) = true');
        });
        it('should handle whitespace around boolean strings', () => {
            const filterFalse = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: [' false '],
            };
            const filterTrue = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: [' true '],
            };
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filterFalse)).toBe('(("table"."is_active")) = false');
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filterTrue)).toBe('(("table"."is_active")) = true');
        });
    });
    describe('notEquals operator', () => {
        it('should handle boolean false correctly', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.NOT_EQUALS,
                values: [false],
            };
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filter)).toBe('((("table"."is_active")) != false OR (("table"."is_active")) IS NULL)');
        });
        it('should handle string "false" correctly (THIS WILL FAIL BEFORE FIX)', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.NOT_EQUALS,
                values: ['false'],
            };
            // This test will fail initially because current implementation uses "true"
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filter)).toBe('((("table"."is_active")) != false OR (("table"."is_active")) IS NULL)');
        });
    });
    describe('isNull and notNull operators', () => {
        it('should handle isNull operator', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.NULL,
                values: [true],
            };
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filter)).toBe('(("table"."is_active")) IS NULL');
        });
        it('should handle notNull operator', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.NOT_NULL,
                values: [true],
            };
            expect((0, filtersCompiler_1.renderBooleanFilterSql)(dimensionSql, filter)).toBe('(("table"."is_active")) IS NOT NULL');
        });
    });
});
describe('Number Filter SQL Injection Prevention', () => {
    const dimensionSql = '("table"."customer_id")';
    const baseFilter = {
        id: 'test-id',
        target: { fieldId: 'customer_id' },
    };
    describe('SQL injection attempts should throw errors', () => {
        it('should reject SQL injection in EQUALS filter', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: ['1) OR 1=1; --'],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toThrow('Invalid number value in filter: "1) OR 1=1; --". Expected a valid number.');
        });
        it('should reject SQL injection with UNION SELECT', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: ['1) UNION SELECT * FROM users; --'],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toThrow('Invalid number value in filter: "1) UNION SELECT * FROM users; --". Expected a valid number.');
        });
        it('should reject SQL injection in NOT_EQUALS filter', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.NOT_EQUALS,
                values: ['1); DELETE FROM customers; --'],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toThrow('Invalid number value in filter: "1); DELETE FROM customers; --". Expected a valid number.');
        });
        it('should reject subquery injection attempts', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: ['SELECT customer_id FROM customers'],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toThrow('Invalid number value in filter: "SELECT customer_id FROM customers". Expected a valid number.');
        });
        it('should reject multiple SQL injection values', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: ['1', '2) OR 1=1; --', '3'],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toThrow('Invalid number value in filter: "2) OR 1=1; --". Expected a valid number.');
        });
        it('should reject SQL injection in comparison operators', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.GREATER_THAN,
                values: ['1 OR 1=1'],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toThrow('Invalid number value in filter: "1 OR 1=1". Expected a valid number.');
        });
        it('should reject SQL injection in BETWEEN operator', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.IN_BETWEEN,
                values: ['1', '100); DROP TABLE customers; --'],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toThrow('Invalid number value in filter: "100); DROP TABLE customers; --". Expected a valid number.');
        });
    });
    describe('Valid number inputs should be accepted', () => {
        it('should accept valid integer values', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: [1, 2, 3],
            };
            expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('(("table"."customer_id")) IN (1,2,3)');
        });
        it('should accept valid decimal values', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: [1.5, 2.7, 3.14159],
            };
            expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('(("table"."customer_id")) IN (1.5,2.7,3.14159)');
        });
        it('should accept negative numbers', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: [-1, -2.5, -100],
            };
            expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('(("table"."customer_id")) IN (-1,-2.5,-100)');
        });
        it('should accept numeric strings that can be converted', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: ['123', '456.78', '-90'],
            };
            expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('(("table"."customer_id")) IN (123,456.78,-90)');
        });
        it('should handle comparison operators with valid numbers', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.GREATER_THAN,
                values: ['100'],
            };
            expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('(("table"."customer_id")) > (100)');
        });
        it('should handle BETWEEN operator with valid numbers', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.IN_BETWEEN,
                values: ['10', '100'],
            };
            expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('(("table"."customer_id")) >= (10) AND (("table"."customer_id")) <= (100)');
        });
    });
    describe('Edge cases and special values', () => {
        it('should reject NaN values', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: [NaN],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toThrow('Invalid number value in filter: "NaN". Expected a valid number.');
        });
        it('should reject Infinity values', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: [Infinity],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toThrow('Invalid number value in filter: "Infinity". Expected a valid number.');
        });
        it('should reject string values that are not numbers', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: ['abc', 'hello world', ''],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toThrow('Invalid number value in filter: "abc". Expected a valid number.');
        });
        it('should reject objects and arrays', () => {
            const filterWithObject = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: [{}],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filterWithObject)).toThrow('Invalid number value in filter: "[object Object]". Expected a valid number.');
            const filterWithArray = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: [[1, 2, 3]],
            };
            expect(() => (0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filterWithArray)).toThrow('Invalid number value in filter: "1,2,3". Expected a valid number.');
        });
        it('should handle exponential notation', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.EQUALS,
                values: ['1e3', '2.5e-4'],
            };
            expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('(("table"."customer_id")) IN (1000,0.00025)');
        });
        it('should return true for comparison operators with empty values', () => {
            const comparisonOperators = [
                filter_1.FilterOperator.GREATER_THAN,
                filter_1.FilterOperator.GREATER_THAN_OR_EQUAL,
                filter_1.FilterOperator.LESS_THAN,
                filter_1.FilterOperator.LESS_THAN_OR_EQUAL,
            ];
            comparisonOperators.forEach((operator) => {
                const filter = {
                    ...baseFilter,
                    operator,
                    values: [],
                };
                expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('true');
            });
        });
        it('should return true for IN_BETWEEN operator with empty values', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.IN_BETWEEN,
                values: [],
            };
            expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('true');
        });
        it('should return true for IN_BETWEEN operator with only one value', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.IN_BETWEEN,
                values: [5],
            };
            expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('true');
        });
        it('should return true for NOT_IN_BETWEEN operator with empty values', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.NOT_IN_BETWEEN,
                values: [],
            };
            expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('true');
        });
        it('should return true for NOT_IN_BETWEEN operator with only one value', () => {
            const filter = {
                ...baseFilter,
                operator: filter_1.FilterOperator.NOT_IN_BETWEEN,
                values: [5],
            };
            expect((0, filtersCompiler_1.renderNumberFilterSql)(dimensionSql, filter)).toBe('true');
        });
    });
});
//# sourceMappingURL=filtersCompiler.test.js.map