diff --git a/.github/workflows/module-size-comparison.yml b/.github/workflows/module-size-comparison.yml
index b343e05b004..aee52f38fda 100644
--- a/.github/workflows/module-size-comparison.yml
+++ b/.github/workflows/module-size-comparison.yml
@@ -4,6 +4,7 @@ on:
pull_request:
branches:
- 'latest'
+ - 'b[0-9][0-9]?.[0-9][0-9]?.[0-9][0-9]?'
types: [opened, synchronize, reopened, ready_for_review]
workflow_dispatch:
inputs:
@@ -36,6 +37,7 @@ jobs:
pr-number: ${{ steps.resolve.outputs.pr-number }}
head-sha: ${{ steps.resolve.outputs.head-sha }}
is-draft: ${{ steps.resolve.outputs.is-draft }}
+ base-ref: ${{ steps.resolve.outputs.base-ref }}
shard-matrix: ${{ steps.resolve.outputs.shard-matrix }}
steps:
- name: Resolve PR details
@@ -55,6 +57,7 @@ jobs:
core.setOutput('pr-number', pr.number.toString());
core.setOutput('head-sha', pr.head.sha);
core.setOutput('is-draft', pr.draft ? 'true' : 'false');
+ core.setOutput('base-ref', pr.base.ref);
return;
}
@@ -79,6 +82,7 @@ jobs:
core.setOutput('pr-number', pr.number.toString());
core.setOutput('head-sha', pr.head.sha);
core.setOutput('is-draft', pr.draft ? 'true' : 'false');
+ core.setOutput('base-ref', pr.base.ref);
# Check for cached base results
check-base-cache:
@@ -88,14 +92,15 @@ jobs:
if: needs.prepare.outputs.is-draft != 'true'
outputs:
cache-hit: ${{ steps.cache-check.outputs.cache-hit }}
- latest-sha: ${{ steps.get-sha.outputs.sha }}
+ base-sha: ${{ steps.get-sha.outputs.sha }}
steps:
- - name: Get latest branch SHA
+ - name: Get base branch SHA
id: get-sha
run: |
- SHA=$(git ls-remote https://github.com/${{ github.repository }} refs/heads/latest | cut -f1)
+ BASE_REF="${{ needs.prepare.outputs.base-ref }}"
+ SHA=$(git ls-remote https://github.com/${{ github.repository }} refs/heads/${BASE_REF} | cut -f1)
echo "sha=${SHA}" >> $GITHUB_OUTPUT
- echo "Latest branch SHA: ${SHA}"
+ echo "Base branch (${BASE_REF}) SHA: ${SHA}"
- name: Check cache for base results
id: cache-check
@@ -131,7 +136,7 @@ jobs:
artifact-prefix: module-size-pr
artifact-suffix: ${{ needs.prepare.outputs.pr-number }}
- # Build and run module size tests on the latest branch (sharded) - only if cache miss
+ # Build and run module size tests on the base branch (sharded) - only if cache miss
module-size-base:
name: Module Size Base (${{ matrix.shard }}/${{ strategy.job-total }})
runs-on: ubuntu-latest
@@ -151,12 +156,12 @@ jobs:
- name: Run module size tests
uses: ./.github/actions/module-size-test
with:
- ref: latest
+ ref: ${{ needs.prepare.outputs.base-ref }}
shard: ${{ matrix.shard }}
total-shards: ${{ strategy.job-total }}
artifact-prefix: module-size-base
artifact-suffix: ${{ needs.prepare.outputs.pr-number }}
- base-ref: latest
+ base-ref: ${{ needs.prepare.outputs.base-ref }}
# Merge base shards and save to cache (only when we had to build)
cache-base-results:
@@ -191,7 +196,7 @@ jobs:
uses: actions/cache/save@v4
with:
path: ./base-results.json
- key: module-size-base-${{ needs.check-base-cache.outputs.latest-sha }}
+ key: module-size-base-${{ needs.check-base-cache.outputs.base-sha }}
# Compare results and post PR comment
compare-and-report:
@@ -206,7 +211,7 @@ jobs:
env:
PR_NUMBER: ${{ needs.prepare.outputs.pr-number }}
CACHE_HIT: ${{ needs.check-base-cache.outputs.cache-hit }}
- LATEST_SHA: ${{ needs.check-base-cache.outputs.latest-sha }}
+ BASE_SHA: ${{ needs.check-base-cache.outputs.base-sha }}
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -237,7 +242,7 @@ jobs:
uses: actions/cache/restore@v4
with:
path: ./base-results.json
- key: module-size-base-${{ env.LATEST_SHA }}
+ key: module-size-base-${{ env.BASE_SHA }}
fail-on-cache-miss: true
# If cache miss, download artifacts and merge
diff --git a/.gitignore b/.gitignore
index 9fbb4125183..1da7fd61bcb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -140,3 +140,4 @@ documentation/ag-grid-docs/test-results/.last-run.json
**/WARP.md
**/modular-mcp.json
!.rulesync/.aiignore
+/.junie/
diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml
index 2335993a432..65a65c8407d 100644
--- a/.idea/jsLibraryMappings.xml
+++ b/.idea/jsLibraryMappings.xml
@@ -8,6 +8,7 @@
+
@@ -15,7 +16,6 @@
-
@@ -24,6 +24,5 @@
-
\ No newline at end of file
diff --git a/.run/Absolute sorting theming test.run.xml b/.run/Absolute sorting theming test.run.xml
index b9517bdb640..2337326cf79 100644
--- a/.run/Absolute sorting theming test.run.xml
+++ b/.run/Absolute sorting theming test.run.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/.run/Preset date sort testing.run.xml b/.run/Preset date sort testing.run.xml
new file mode 100644
index 00000000000..ad6883be45b
--- /dev/null
+++ b/.run/Preset date sort testing.run.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/SSRM Preset date sort testing.run.xml b/.run/SSRM Preset date sort testing.run.xml
new file mode 100644
index 00000000000..4b53dd0a1a2
--- /dev/null
+++ b/.run/SSRM Preset date sort testing.run.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/SSRM basic no cache.run.xml b/.run/SSRM basic no cache.run.xml
index eb5918fe059..506bc960c56 100644
--- a/.run/SSRM basic no cache.run.xml
+++ b/.run/SSRM basic no cache.run.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/documentation/ag-grid-docs/src/content/docs/filter-date/_examples/built-in-date-ranges/example.spec.ts b/documentation/ag-grid-docs/src/content/docs/filter-date/_examples/built-in-date-ranges/example.spec.ts
new file mode 100644
index 00000000000..ed79767b830
--- /dev/null
+++ b/documentation/ag-grid-docs/src/content/docs/filter-date/_examples/built-in-date-ranges/example.spec.ts
@@ -0,0 +1,11 @@
+import { clickAllButtons, ensureGridReady, test, waitForGridContent } from '@utils/grid/test-utils';
+
+test.agExample(import.meta, () => {
+ test.eachFramework('Example', async ({ page }) => {
+ // PLACEHOLDER - MINIMAL TEST TO ENSURE GRID LOADS WITHOUT ERRORS
+ await ensureGridReady(page);
+ await waitForGridContent(page);
+ await clickAllButtons(page);
+ // END PLACEHOLDER
+ });
+});
diff --git a/documentation/ag-grid-docs/src/content/docs/filter-date/_examples/built-in-date-ranges/index.html b/documentation/ag-grid-docs/src/content/docs/filter-date/_examples/built-in-date-ranges/index.html
new file mode 100644
index 00000000000..378fad58398
--- /dev/null
+++ b/documentation/ag-grid-docs/src/content/docs/filter-date/_examples/built-in-date-ranges/index.html
@@ -0,0 +1 @@
+
diff --git a/documentation/ag-grid-docs/src/content/docs/filter-date/_examples/built-in-date-ranges/main.ts b/documentation/ag-grid-docs/src/content/docs/filter-date/_examples/built-in-date-ranges/main.ts
new file mode 100644
index 00000000000..3b0658dc753
--- /dev/null
+++ b/documentation/ag-grid-docs/src/content/docs/filter-date/_examples/built-in-date-ranges/main.ts
@@ -0,0 +1,80 @@
+import type { ColDef, GridApi, GridOptions } from 'ag-grid-community';
+import {
+ ClientSideRowModelModule,
+ DateFilterModule,
+ ModuleRegistry,
+ TextFilterModule,
+ ValidationModule,
+ createGrid,
+} from 'ag-grid-community';
+
+ModuleRegistry.registerModules([
+ ClientSideRowModelModule,
+ DateFilterModule,
+ TextFilterModule,
+ ...(process.env.NODE_ENV !== 'production' ? [ValidationModule] : []),
+]);
+
+const columnDefs: ColDef[] = [
+ { field: 'athlete' },
+ {
+ field: 'date',
+ filter: 'agDateColumnFilter',
+ filterParams: {
+ // Enable built-in named & relative date ranges
+ filterOptions: [
+ 'empty',
+ 'yesterday',
+ 'today',
+ 'tomorrow',
+ 'last7Days',
+ 'lastWeek',
+ 'thisWeek',
+ 'nextWeek',
+ 'last30Days',
+ 'lastMonth',
+ 'thisMonth',
+ 'nextMonth',
+ 'last90Days',
+ 'lastQuarter',
+ 'thisQuarter',
+ 'nextQuarter',
+ 'lastYear',
+ 'thisYear',
+ 'yearToDate',
+ 'nextYear',
+ 'last6Months',
+ 'last12Months',
+ 'last24Months',
+ ],
+ },
+ },
+];
+
+let gridApi: GridApi;
+
+const gridOptions: GridOptions = {
+ columnDefs: columnDefs,
+ defaultColDef: {
+ flex: 1,
+ minWidth: 150,
+ filter: true,
+ },
+};
+
+// Setup the grid after the page has finished loading
+document.addEventListener('DOMContentLoaded', function () {
+ const gridDiv = document.querySelector('#myGrid')!;
+ gridApi = createGrid(gridDiv, gridOptions);
+ fetch('https://www.ag-grid.com/example-assets/olympic-winners.json')
+ .then((response) => response.json())
+ .then((data) =>
+ gridApi.setGridOption(
+ 'rowData',
+ data.map((d: IOlympicData) => ({
+ ...d,
+ date: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000 * (Math.random() * 0.5 - Math.random())),
+ }))
+ )
+ );
+});
diff --git a/documentation/ag-grid-docs/src/content/docs/filter-date/index.mdoc b/documentation/ag-grid-docs/src/content/docs/filter-date/index.mdoc
index 591d7ef19cc..dac894c7e32 100644
--- a/documentation/ag-grid-docs/src/content/docs/filter-date/index.mdoc
+++ b/documentation/ag-grid-docs/src/content/docs/filter-date/index.mdoc
@@ -37,7 +37,7 @@ const gridOptions = {
## Date Filter Parameters
-Date Filters are configured though the `filterParams` attribute of the column definition (`IDateFilterParams` interface):
+Date Filters are configured through the `filterParams` attribute of the column definition (`IDateFilterParams` interface):
{% interfaceDocumentation interfaceName="IDateFilterParams" overrideSrc="filter-date/date-filter-params.json" config={"description":"", "sortAlphabetically":true} /%}
@@ -130,7 +130,7 @@ The example below demonstrates configuring a comparator:
The Filter Model describes the current state of the applied Date Filter. The Date Filter Model represents the Date as a string in format `'YYYY-MM-DD'`, however when doing comparisons the date is provided as a JavaScript `Date` object as that's what date pickers typically work with. The model uses string representation to make it easier to save and avoid any timezone issues.
-If only one [Filter Condition](./filter-conditions/) is set, this will be a `DateFilterModel`:
+If only one [Filter Condition](./filter-conditions/#filter-options) is set, this will be a `DateFilterModel`:
{% interfaceDocumentation interfaceName="DateFilterModel" config={"description":""} /%}
@@ -180,16 +180,16 @@ The Date Filter presents a list of [Filter Options](./filter-conditions/#filter-
The list of options is as follows:
-| Option Name | Option Key | Included by Default |
-| ----------------------- | --------------------- | ------------------- |
-| Equals | `equals` | Yes |
-| Does not equal | `notEqual` | Yes |
-| Before | `lessThan` | Yes |
-| After | `greaterThan` | Yes |
-| Between | `inRange` | Yes |
-| Blank | `blank` | Yes |
-| Not blank | `notBlank` | Yes |
-| Choose one | `empty` | No |
+| Option Name | Option Key | Included by Default |
+|----------------|---------------|---------------------|
+| Equals | `equals` | Yes |
+| Does not equal | `notEqual` | Yes |
+| Before | `lessThan` | Yes |
+| After | `greaterThan` | Yes |
+| Between | `inRange` | Yes |
+| Blank | `blank` | Yes |
+| Not blank | `notBlank` | Yes |
+| Choose one | `empty` | No |
Note that the `empty` filter option is primarily used when creating [Custom Filter Options](./filter-conditions/#custom-filter-options). When 'Choose one' is displayed, the filter is not active.
@@ -197,6 +197,78 @@ The default option for the Date Filter is `equals`.
When providing filter options, the default filter option (or the first option if no default set) must be an option that displays an input or the `empty` filter option (as a filter option with no inputs would mean the filter is active by default).
+## Built-in Named & Relative Date Ranges
+
+Date Filter supports a set of predefined named and relative date ranges to make common filtering tasks easier. These ranges are relative to the browser local time. These are ideal for users who want to filter by familiar time periods like "Last Week", "Year to Date", or "Next 30 Days" without extending a grid with a custom solution.
+
+### Enabling Built-in Date Ranges
+
+To enable the built-in date ranges, add them to the `filterOptions` array in your date filter configuration. The options are not included by default.
+
+#### Example: Enable Built-in Date Ranges
+
+{% gridExampleRunner title="Built-in Date Ranges" name="built-in-date-ranges" /%}
+
+Example above uses following configuration:
+
+```ts
+// Enable built-in date ranges
+const columnDefs: ColDef[] = [
+ {
+ filter: 'agDateColumnFilter',
+ filterParams: {
+ // Enable built-in named & relative date ranges
+ filterOptions: [
+ 'empty', // optional: show 'Choose one' option first
+ 'yesterday',
+ 'today',
+ 'tomorrow',
+ 'last7Days',
+ 'lastWeek',
+ 'thisWeek',
+ 'nextWeek',
+ 'last30Days',
+ 'lastMonth',
+ // ... All other preset ranges
+ ],
+ // Other filter settings...
+ },
+ },
+];
+```
+
+### Available Built-in Date Filter Options
+
+| Option Name | Option Key | Time Range Start >= | Time Range End < |
+|--------------------|----------------|----------------------------------|:------------------------------|
+| Today | `today` | `Start Of Today` | `Start Of Tomorrow` |
+| Yesterday | `yesterday` | `Start Of Yesterday` | `Start Of Today` |
+| Tomorrow | `tomorrow` | `Start Of Tomorrow` | `Start Of Day After Tomorrow` |
+| This Week | `thisWeek` | `Start Of Current Week` | `Start Of Next Week` |
+| Last Week | `lastWeek` | `Start Of Previous Week` | `Start Of Current Week` |
+| Next Week | `nextWeek` | `Start Of Next Week` | `Start Of Week After Next` |
+| This Month | `thisMonth` | `Start Of Current Month` | `Start Of Next Month` |
+| Last Month | `lastMonth` | `Start Of Previous Month` | `Start Of Current Month` |
+| Next Month | `nextMonth` | `Start Of Next Month` | `Start Of Month After Next` |
+| This Quarter | `thisQuarter` | `Start Of Current Quarter` | `Start Of Next Quarter` |
+| Last Quarter | `lastQuarter` | `Start Of Previous Quarter` | `Start Of Current Quarter` |
+| Next Quarter | `nextQuarter` | `Start Of Next Quarter` | `Start Of Quarter After Next` |
+| This Year | `thisYear` | `Start Of Current Year` | `Start Of Next Year` |
+| Last Year | `lastYear` | `Start Of Previous Year` | `Start Of Current Year` |
+| Next Year | `nextYear` | `Start Of Next Year` | `Start Of Year After Next` |
+| Year to Date (YTD) | `yearToDate` | `Start Of Current Year` | `Start Of Tomorrow` |
+| Last 7 Days | `last7Days` | `Start Of Today minus 7 days` | `Start Of Tomorrow` |
+| Last 30 Days | `last30Days` | `Start Of Today minus 30 days` | `Start Of Tomorrow` |
+| Last 90 Days | `last90Days` | `Start Of Today minus 90 days` | `Start Of Tomorrow` |
+| Last 6 Months | `last6Months` | `Start Of Today minus 6 months` | `Start Of Tomorrow` |
+| Last 12 Months | `last12Months` | `Start Of Today minus 12 months` | `Start Of Tomorrow` |
+| Last 24 Months | `last24Months` | `Start Of Today minus 24 months` | `Start Of Tomorrow` |
+
+
+{% note %}
+`Start Of Today`, `Start Of Tomorrow`, `Start Of XXX` point to the beginning of the corresponding day, e.g. `00:00:00.000` in browser local timezone.
+{% /note %}
+
## Range Input Validation and Error States
When using the `inRange` filter type, the grid performs input validation to ensure the bounds of the range produce a valid filter; that is, where the start date is earlier than the end date.
@@ -268,4 +340,4 @@ The Date Filter is not affected by data changes. When the grid data is updated,
## Next Up
-Continue to the next section to learn about [Set Filters](./filter-set/).
+Continue to the next section to learn about [Set Filters](./filter-set/).
\ No newline at end of file
diff --git a/jest.preset.js b/jest.preset.js
index 55081f0edf4..c6ff4e607c9 100644
--- a/jest.preset.js
+++ b/jest.preset.js
@@ -1,3 +1,3 @@
+process.env.TZ = 'UTC';
const nxPreset = require('@nx/jest/preset').default;
-
module.exports = { ...nxPreset, coverageReporters: [] };
diff --git a/packages/ag-grid-community/src/agStack/utils/function.ts b/packages/ag-grid-community/src/agStack/utils/function.ts
index 9eb0809053f..2b1895b3f7c 100644
--- a/packages/ag-grid-community/src/agStack/utils/function.ts
+++ b/packages/ag-grid-community/src/agStack/utils/function.ts
@@ -65,7 +65,7 @@ export function _batchCall(
}
/**
- * Creates a debounced function a function, and attach it to a bean for lifecycle
+ * Creates a debounced function, and attach it to a bean for lifecycle
* @param {Function} func The function to be debounced
* @param {number} delay The time in ms to debounce
* @returns {Function} The debounced function
diff --git a/packages/ag-grid-community/src/filter/filterLocaleText.ts b/packages/ag-grid-community/src/filter/filterLocaleText.ts
index d0d8ae4dcaa..4007a4abe29 100644
--- a/packages/ag-grid-community/src/filter/filterLocaleText.ts
+++ b/packages/ag-grid-community/src/filter/filterLocaleText.ts
@@ -48,6 +48,30 @@ const FILTER_LOCALE_TEXT = {
filterSummaryLessThan: '<',
filterSummaryLessThanOrEqual: '<=',
filterSummaryInRange: 'between',
+
+ yesterday: 'Yesterday',
+ today: 'Today',
+ tomorrow: 'Tomorrow',
+ last7Days: 'Last 7 Days',
+ lastWeek: 'Last Week',
+ thisWeek: 'This Week',
+ nextWeek: 'Next Week',
+ last30Days: 'Last 30 Days',
+ lastMonth: 'Last Month',
+ thisMonth: 'This Month',
+ nextMonth: 'Next Month',
+ last90Days: 'Last 90 Days',
+ lastQuarter: 'Last Quarter',
+ thisQuarter: 'This Quarter',
+ nextQuarter: 'Next Quarter',
+ lastYear: 'Last Year',
+ thisYear: 'This Year',
+ yearToDate: 'Year To Date',
+ nextYear: 'Next Year',
+ last6Months: 'Last 6 Months',
+ last12Months: 'Last 12 Months',
+ last24Months: 'Last 24 Months',
+
filterSummaryInRangeValues: (variableValues: string[]) => `(${variableValues[0]}, ${variableValues[1]})`,
filterSummaryTextQuote: (variableValues: string[]) => `"${variableValues[0]}"`,
minDateValidation: (variableValues: string[]) => `Date must be after ${variableValues[0]}`,
diff --git a/packages/ag-grid-community/src/filter/provided/date/dateFilter.ts b/packages/ag-grid-community/src/filter/provided/date/dateFilter.ts
index 3c5d4133672..d09d20de3ea 100644
--- a/packages/ag-grid-community/src/filter/provided/date/dateFilter.ts
+++ b/packages/ag-grid-community/src/filter/provided/date/dateFilter.ts
@@ -284,9 +284,10 @@ export class DateFilter extends SimpleFilter = {};
-
+ const { params, filterType } = this;
const values = this.getValues(position);
- const separator = this.params.useIsoSeparator ? 'T' : ' ';
+
+ const separator = params.useIsoSeparator ? 'T' : ' ';
if (values.length > 0) {
model.dateFrom = _serialiseDate(values[0], true, separator);
}
@@ -297,7 +298,7 @@ export class DateFilter extends SimpleFilter {
+ const BASE = 'Wed Apr 08 2020 12:34:56 GMT+0000 (Coordinated Universal Time)';
+
+ const ANSWERS = {
+ startOfTodayMinus24months: 'Sun Apr 08 2018 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfPreviousYear: 'Tue Jan 01 2019 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfTodayMinus12months: 'Mon Apr 08 2019 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfTodayMinus6months: 'Tue Oct 08 2019 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfCurrentYear: 'Wed Jan 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfPreviousQuarter: 'Wed Jan 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfTodayMinus90days: 'Thu Jan 09 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfPreviousMonth: 'Sun Mar 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfTodayMinus30days: 'Mon Mar 09 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfPreviousWeek: 'Mon Mar 30 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ previousMonth: 'Tue Mar 31 2020',
+ previousQuarter: 'Tue Mar 31 2020',
+ startOfCurrentQuarter: 'Wed Apr 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfCurrentMonth: 'Wed Apr 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfTodayMinus7days: 'Wed Apr 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ previousWeek: 'Sun Apr 05 2020',
+ startOfCurrentWeek: 'Mon Apr 06 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfYesterday: 'Tue Apr 07 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ previousDay: 'Tue Apr 07 2020',
+ startOfToday: 'Wed Apr 08 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfTomorrow: 'Thu Apr 09 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfDayAfterTomorrow: 'Fri Apr 10 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfNextWeek: 'Mon Apr 13 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfWeekAfterNext: 'Mon Apr 20 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfNextMonth: 'Fri May 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfMonthAfterNext: 'Mon Jun 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfNextQuarter: 'Wed Jul 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfQuarterAfterNext: 'Thu Oct 01 2020 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfNextYear: 'Fri Jan 01 2021 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ startOfYearAfterNext: 'Sat Jan 01 2022 00:00:00 GMT+0000 (Coordinated Universal Time)',
+ };
+
+ let FROM: Date;
+ let TO: Date;
+
+ beforeEach(() => {
+ [FROM, TO] = [new Date(BASE), new Date(BASE)];
+ });
+
+ it('validate answers', () =>
+ Object.values(ANSWERS).forEach((date, index, arr) => {
+ if (arr[index + 1] && new Date(date) > new Date(arr[index + 1])) {
+ expect(''.toString()).toBe(`${date.toString()} <= ${arr[index + 1].toString()}`);
+ }
+ }));
+
+ describe.each([
+ ['today', [ANSWERS.startOfToday, ANSWERS.startOfTomorrow]],
+ ['yesterday', [ANSWERS.startOfYesterday, ANSWERS.startOfToday]],
+ ['tomorrow', [ANSWERS.startOfTomorrow, ANSWERS.startOfDayAfterTomorrow]],
+ ['thisWeek', [ANSWERS.startOfCurrentWeek, ANSWERS.startOfNextWeek]],
+ ['lastWeek', [ANSWERS.startOfPreviousWeek, ANSWERS.startOfCurrentWeek]],
+ ['nextWeek', [ANSWERS.startOfNextWeek, ANSWERS.startOfWeekAfterNext]],
+ ['thisMonth', [ANSWERS.startOfCurrentMonth, ANSWERS.startOfNextMonth]],
+ ['lastMonth', [ANSWERS.startOfPreviousMonth, ANSWERS.startOfCurrentMonth]],
+ ['nextMonth', [ANSWERS.startOfNextMonth, ANSWERS.startOfMonthAfterNext]],
+ ['thisQuarter', [ANSWERS.startOfCurrentQuarter, ANSWERS.startOfNextQuarter]],
+ ['lastQuarter', [ANSWERS.startOfPreviousQuarter, ANSWERS.startOfCurrentQuarter]],
+ ['nextQuarter', [ANSWERS.startOfNextQuarter, ANSWERS.startOfQuarterAfterNext]],
+ ['thisYear', [ANSWERS.startOfCurrentYear, ANSWERS.startOfNextYear]],
+ ['lastYear', [ANSWERS.startOfPreviousYear, ANSWERS.startOfCurrentYear]],
+ ['nextYear', [ANSWERS.startOfNextYear, ANSWERS.startOfYearAfterNext]],
+ ['yearToDate', [ANSWERS.startOfCurrentYear, ANSWERS.startOfTomorrow]],
+ ['last7Days', [ANSWERS.startOfTodayMinus7days, ANSWERS.startOfTomorrow]],
+ ['last30Days', [ANSWERS.startOfTodayMinus30days, ANSWERS.startOfTomorrow]],
+ ['last90Days', [ANSWERS.startOfTodayMinus90days, ANSWERS.startOfTomorrow]],
+ ['last6Months', [ANSWERS.startOfTodayMinus6months, ANSWERS.startOfTomorrow]],
+ ['last12Months', [ANSWERS.startOfTodayMinus12months, ANSWERS.startOfTomorrow]],
+ ['last24Months', [ANSWERS.startOfTodayMinus24months, ANSWERS.startOfTomorrow]],
+ ])('%s', (fnName, expected) =>
+ it('returns correct from/to', () =>
+ expect(
+ presetDateFilterTypeRelativeFromToMap[fnName](FROM, TO).map((d: Date) => d.toString())
+ ).toStrictEqual(expected))
+ );
+ describe.each([
+ ['setStartOfDay', ANSWERS.startOfToday],
+ ['setStartOfWeek', ANSWERS.startOfCurrentWeek],
+ ['setStartOfNextDay', ANSWERS.startOfTomorrow],
+ ['setStartOfNextWeek', ANSWERS.startOfNextWeek],
+ ['setStartOfMonth', ANSWERS.startOfCurrentMonth],
+ ['setStartOfNextMonth', ANSWERS.startOfNextMonth],
+ ['setStartOfQuarter', ANSWERS.startOfCurrentQuarter],
+ ['setStartOfNextQuarter', ANSWERS.startOfNextQuarter],
+ ['setStartOfYear', ANSWERS.startOfCurrentYear],
+ ['setStartOfNextYear', ANSWERS.startOfNextYear],
+ ['setPreviousDay', ANSWERS.previousDay],
+ ['setPreviousWeek', ANSWERS.previousWeek],
+ ['setPreviousMonth', ANSWERS.previousMonth],
+ ['setPreviousQuarter', ANSWERS.previousQuarter],
+ ])('%s', (fnName, expected) =>
+ it('works', () => expect(presetDateFilterTypeRelativeFromToMap[fnName](FROM).toString()).toContain(expected))
+ );
+});
diff --git a/packages/ag-grid-community/src/filter/provided/date/dateFilterHandler.ts b/packages/ag-grid-community/src/filter/provided/date/dateFilterHandler.ts
index 3d9a77bed2a..7879500ef23 100644
--- a/packages/ag-grid-community/src/filter/provided/date/dateFilterHandler.ts
+++ b/packages/ag-grid-community/src/filter/provided/date/dateFilterHandler.ts
@@ -1,4 +1,5 @@
import type { Comparator } from '../iScalarFilter';
+import type { ISimpleFilterModelPresetType, Tuple } from '../iSimpleFilter';
import { ScalarFilterHandler } from '../scalarFilterHandler';
import { DEFAULT_DATE_FILTER_OPTIONS } from './dateFilterConstants';
import { DateFilterModelFormatter } from './dateFilterModelFormatter';
@@ -22,9 +23,23 @@ function defaultDateComparator(filterDate: Date, cellValue: any): number {
export class DateFilterHandler extends ScalarFilterHandler {
public readonly filterType = 'date' as const;
protected readonly FilterModelFormatterClass = DateFilterModelFormatter;
+ private readonly filterTypeToRangeCache = new Map();
constructor() {
super(mapValuesFromDateFilterModel, DEFAULT_DATE_FILTER_OPTIONS);
+ this.refreshFilterBaseDate();
+ }
+
+ private refreshFilterBaseDate(): void {
+ if (this.isAlive()) {
+ this.filterTypeToRangeCache.clear();
+ const filterBaseDateTimeout = setTimeout(
+ () => this.refreshFilterBaseDate(),
+ // this evaluates to a number of ms between NOW and beginning of tomorrow MINUS 1 minute
+ setStartOfNextDay(new Date()).getTime() - Date.now() - 60 * 1000
+ );
+ this.addDestroyFunc(() => clearTimeout(filterBaseDateTimeout));
+ }
}
protected override comparator(): Comparator {
@@ -35,4 +50,244 @@ export class DateFilterHandler extends ScalarFilterHandler,
+ cellValue: Date,
+ filterModel: DateFilterModel
+ ): boolean {
+ const type = filterModel.type;
+ const comparator = this.comparator();
+
+ if (!this.isValid(cellValue)) {
+ return type === 'notEqual' || type === 'notBlank';
+ }
+ const typeAsPreset = type as ISimpleFilterModelPresetType;
+ const presetDateRangeFn = presetDateFilterTypeRelativeFromToMap[typeAsPreset] as RelativeRangeFn;
+ if (presetDateRangeFn) {
+ // indicates we are in preset time ranges space
+ let cache = this.filterTypeToRangeCache.get(typeAsPreset);
+ if (!cache) {
+ cache = presetDateRangeFn(new Date(), new Date());
+ this.filterTypeToRangeCache.set(typeAsPreset, cache);
+ }
+ const [from, to] = cache;
+ return comparator(from, cellValue) >= 0 && comparator(to, cellValue) < 0;
+ }
+
+ return super.evaluateNonNullValue(values, cellValue, filterModel);
+ }
}
+
+type RelativeDateFn = (date: Date) => Date;
+type RelativeRangeFn = (from: Date, to: Date) => [Date, Date];
+
+// Reusable fns
+const setStartOfDay: RelativeDateFn = (date: Date) => {
+ date.setHours(0, 0, 0, 0);
+ return date;
+};
+
+const setStartOfWeek: RelativeDateFn = (date: Date) => {
+ const day = date.getDay();
+ const diff = day === 0 ? 6 : day - 1;
+ date.setDate(date.getDate() - diff);
+
+ return setStartOfDay(date);
+};
+const setPreviousNDay = (date: Date, n = 1) => {
+ date.setDate(date.getDate() - n);
+ return date;
+};
+const setStartOfNextDay: RelativeDateFn = (date: Date) => {
+ date.setDate(date.getDate() + 1);
+ return setStartOfDay(date);
+};
+const setStartOfNextWeek: RelativeDateFn = (date: Date) => {
+ setStartOfWeek(date);
+ date.setDate(date.getDate() + 6); // end of week
+ return setStartOfNextDay(date);
+};
+const setStartOfMonth: RelativeDateFn = (date: Date) => {
+ date.setDate(1);
+ return setStartOfDay(date);
+};
+const setStartOfNextMonth: RelativeDateFn = (date: Date) => {
+ date.setDate(1);
+ date.setMonth(date.getMonth() + 1);
+ return setStartOfDay(date);
+};
+const setStartOfQuarter: RelativeDateFn = (date: Date) => {
+ const quarter = Math.floor(date.getMonth() / 3); // [0, 3]
+ date.setMonth(quarter * 3);
+ return setStartOfMonth(date);
+};
+
+const setStartOfNextQuarter: RelativeDateFn = (date: Date) => {
+ const quarter = Math.floor(date.getMonth() / 3); // [0, 3]
+ date.setMonth(quarter * 3 + 2);
+ return setStartOfNextMonth(date);
+};
+
+const setStartOfYear: RelativeDateFn = (date: Date) => {
+ date.setMonth(0, 1);
+ return setStartOfDay(date);
+};
+const setStartOfNextYear: RelativeDateFn = (date: Date) => {
+ date.setMonth(12, 0);
+ return setStartOfNextDay(date);
+};
+const setPreviousDay: RelativeDateFn = (date: Date) => setPreviousNDay(date);
+const setPreviousWeek: RelativeDateFn = (date: Date) => setPreviousDay(setStartOfWeek(date));
+const setPreviousMonth: RelativeDateFn = (date: Date) => setPreviousDay(setStartOfMonth(date));
+const setPreviousQuarter: RelativeDateFn = (date: Date) => setPreviousDay(setStartOfQuarter(date));
+
+// Range fns
+const today: RelativeRangeFn = (from: Date, to: Date) => [setStartOfDay(from), setStartOfNextDay(to)];
+const yesterday: RelativeRangeFn = (from: Date, to: Date) => today(setPreviousDay(from), setPreviousDay(to));
+const thisWeek: RelativeRangeFn = (from: Date, to: Date) => [setStartOfWeek(from), setStartOfNextWeek(to)];
+const lastWeek: RelativeRangeFn = (from: Date, to: Date) => thisWeek(setPreviousWeek(from), setPreviousWeek(to));
+const thisMonth: RelativeRangeFn = (from: Date, to: Date) => [setStartOfMonth(from), setStartOfNextMonth(to)];
+const lastMonth: RelativeRangeFn = (from: Date, to: Date) => thisMonth(setPreviousMonth(from), setPreviousMonth(to));
+const thisQuarter: RelativeRangeFn = (from: Date, to: Date) => [setStartOfQuarter(from), setStartOfNextQuarter(to)];
+const lastQuarter: RelativeRangeFn = (from: Date, to: Date) =>
+ thisQuarter(setPreviousQuarter(from), setPreviousQuarter(to));
+const thisYear: RelativeRangeFn = (from: Date, to: Date) => [setStartOfYear(from), setStartOfNextYear(to)];
+const yearToDate: RelativeRangeFn = (from: Date, to: Date) => [setStartOfYear(from), setStartOfNextDay(to)];
+const last7Days: RelativeRangeFn = (from: Date, to: Date) => [
+ setStartOfDay(setPreviousNDay(from, 7)),
+ setStartOfNextDay(to),
+];
+const last30Days: RelativeRangeFn = (from: Date, to: Date) => [
+ setStartOfDay(setPreviousNDay(from, 30)),
+ setStartOfNextDay(to),
+];
+const last90Days: RelativeRangeFn = (from: Date, to: Date) => [
+ setStartOfDay(setPreviousNDay(from, 90)),
+ setStartOfNextDay(to),
+];
+
+const last6Months: RelativeRangeFn = (from: Date, to: Date) => {
+ from.setFullYear(from.getFullYear() - 1);
+ from.setMonth(from.getMonth() + 6);
+ return [setStartOfDay(from), setStartOfNextDay(to)];
+};
+const last12Months: RelativeRangeFn = (from: Date, to: Date) => {
+ from.setFullYear(from.getFullYear() - 1);
+ return [setStartOfDay(from), setStartOfNextDay(to)];
+};
+const last24Months: RelativeRangeFn = (from: Date, to: Date) => {
+ from.setFullYear(from.getFullYear() - 2);
+ return [setStartOfDay(from), setStartOfNextDay(to)];
+};
+const lastYear: RelativeRangeFn = (from: Date, to: Date) => {
+ from.setFullYear(from.getFullYear() - 1);
+ to.setFullYear(to.getFullYear() - 1);
+ return thisYear(from, to);
+};
+const nextYear: RelativeRangeFn = (from: Date, to: Date) => {
+ from.setFullYear(from.getFullYear() + 1);
+ to.setFullYear(to.getFullYear() + 1);
+ return thisYear(from, to);
+};
+const nextQuarter: RelativeRangeFn = (from: Date, to: Date) => {
+ from.setMonth(from.getMonth() + 3);
+ to.setMonth(to.getMonth() + 3);
+ return thisQuarter(from, to);
+};
+const nextMonth: RelativeRangeFn = (from: Date, to: Date) => {
+ from.setMonth(from.getMonth() + 1);
+ to.setMonth(to.getMonth() + 1);
+ return thisMonth(from, to);
+};
+const nextWeek: RelativeRangeFn = (from: Date, to: Date) => {
+ from.setDate(from.getDate() + 7);
+ to.setDate(to.getDate() + 7);
+ return thisWeek(from, to);
+};
+const tomorrow: RelativeRangeFn = (from: Date, to: Date) => {
+ from.setDate(from.getDate() + 1);
+ to.setDate(to.getDate() + 1);
+ return today(from, to);
+};
+
+/**
+ * Spec:
+ * Today today [startOfToday, startOfTomorrow)
+ * Yesterday yesterday [startOfYesterday, startOfToday)
+ * Tomorrow tomorrow [startOfTomorrow, startOfDayAfterTomorrow)
+ * This Week thisWeek [startOfCurrentWeek, startOfNextWeek)(locale-specific week start)
+ * Last Week lastWeek [startOfPreviousWeek, startOfCurrentWeek)
+ * Next Week nextWeek [startOfNextWeek, startOfWeekAfterNext)
+ * This Month thisMonth [startOfCurrentMonth, startOfNextMonth)
+ * Last Month lastMonth [startOfPreviousMonth, startOfCurrentMonth)
+ * Next Month nextMonth [startOfNextMonth, startOfMonthAfterNext)
+ * This Quarter thisQuarter [startOfCurrentQuarter, startOfNextQuarter)
+ * Last Quarter lastQuarter [startOfPreviousQuarter, startOfCurrentQuarter)
+ * Next Quarter nextQuarter [startOfNextQuarter, startOfQuarterAfterNext)
+ * This Year thisYear [startOfCurrentYear, startOfNextYear)
+ * Last Year lastYear [startOfPreviousYear, startOfCurrentYear)
+ * Next Year nextYear [startOfNextYear, startOfYearAfterNext)
+ * Year to Date (YTD) yearToDate [startOfCurrentYear, startOfTomorrow)
+ * Last 7 days last7Days [startOfToday − 7 days, startOfTomorrow)
+ * Last 30 days last30Days [startOfToday − 30 days, startOfTomorrow)
+ * Last 90 days last90Days [startOfToday − 90 days, startOfTomorrow)
+ * Last 6 months last6Months [startOfToday − 6 months, startOfTomorrow)
+ * Last 12 months last12Months [startOfToday − 12 months, startOfTomorrow)
+ * Last 24 months last24Months [startOfToday − 24 months, startOfTomorrow)
+ */
+export const presetDateFilterTypeRelativeFromToMap: Record<
+ | ISimpleFilterModelPresetType
+ | 'setStartOfDay'
+ | 'setStartOfWeek'
+ | 'setStartOfNextDay'
+ | 'setStartOfNextWeek'
+ | 'setStartOfMonth'
+ | 'setStartOfNextMonth'
+ | 'setStartOfQuarter'
+ | 'setStartOfNextQuarter'
+ | 'setStartOfYear'
+ | 'setStartOfNextYear'
+ | 'setPreviousDay'
+ | 'setPreviousWeek'
+ | 'setPreviousMonth'
+ | 'setPreviousQuarter',
+ RelativeRangeFn | RelativeDateFn
+> = {
+ today,
+ yesterday,
+ tomorrow,
+ thisWeek,
+ lastWeek,
+ nextWeek,
+ thisMonth,
+ lastMonth,
+ nextMonth,
+ thisQuarter,
+ lastQuarter,
+ nextQuarter,
+ thisYear,
+ lastYear,
+ nextYear,
+ yearToDate,
+ last7Days,
+ last30Days,
+ last90Days,
+ last6Months,
+ last12Months,
+ last24Months,
+ setStartOfDay,
+ setStartOfWeek,
+ setStartOfNextDay,
+ setStartOfNextWeek,
+ setStartOfMonth,
+ setStartOfNextMonth,
+ setStartOfQuarter,
+ setStartOfNextQuarter,
+ setStartOfYear,
+ setStartOfNextYear,
+ setPreviousDay,
+ setPreviousWeek,
+ setPreviousMonth,
+ setPreviousQuarter,
+};
diff --git a/packages/ag-grid-community/src/filter/provided/iSimpleFilter.ts b/packages/ag-grid-community/src/filter/provided/iSimpleFilter.ts
index 8794f372dbf..0abdea07871 100644
--- a/packages/ag-grid-community/src/filter/provided/iSimpleFilter.ts
+++ b/packages/ag-grid-community/src/filter/provided/iSimpleFilter.ts
@@ -81,6 +81,30 @@ export interface ISimpleFilterParams extends IProvidedFilterParams {
filterPlaceholder?: FilterPlaceholderFunction | string;
}
+export type ISimpleFilterModelPresetType =
+ | 'today'
+ | 'yesterday'
+ | 'tomorrow'
+ | 'thisWeek'
+ | 'lastWeek'
+ | 'nextWeek'
+ | 'thisMonth'
+ | 'lastMonth'
+ | 'nextMonth'
+ | 'thisQuarter'
+ | 'lastQuarter'
+ | 'nextQuarter'
+ | 'thisYear'
+ | 'lastYear'
+ | 'nextYear'
+ | 'yearToDate'
+ | 'last7Days'
+ | 'last30Days'
+ | 'last90Days'
+ | 'last6Months'
+ | 'last12Months'
+ | 'last24Months';
+
export type ISimpleFilterModelType =
| 'empty'
| 'equals'
@@ -95,7 +119,9 @@ export type ISimpleFilterModelType =
| 'startsWith'
| 'endsWith'
| 'blank'
- | 'notBlank';
+ | 'notBlank'
+ | ISimpleFilterModelPresetType;
+
export interface ISimpleFilterModel extends ProvidedFilterModel {
/** One of the filter options, e.g. `'equals'` */
type?: ISimpleFilterModelType | null;
diff --git a/packages/ag-grid-community/src/filter/provided/scalarFilterHandler.ts b/packages/ag-grid-community/src/filter/provided/scalarFilterHandler.ts
index 0810019e1e7..9c9716a0643 100644
--- a/packages/ag-grid-community/src/filter/provided/scalarFilterHandler.ts
+++ b/packages/ag-grid-community/src/filter/provided/scalarFilterHandler.ts
@@ -66,8 +66,8 @@ export abstract class ScalarFilterHandler<
}
const comparator = this.comparator();
- const compareResult = values[0] != null ? comparator(values[0], cellValue) : 0;
+ const compareResult = values[0] != null ? comparator(values[0], cellValue) : 0;
switch (type) {
case 'equals':
return compareResult === 0;
diff --git a/packages/ag-grid-community/src/filter/provided/simpleFilterUtils.ts b/packages/ag-grid-community/src/filter/provided/simpleFilterUtils.ts
index dfc300ce51f..02a03a6f13b 100644
--- a/packages/ag-grid-community/src/filter/provided/simpleFilterUtils.ts
+++ b/packages/ag-grid-community/src/filter/provided/simpleFilterUtils.ts
@@ -43,6 +43,34 @@ export function validateAndUpdateConditions(conditions: M[], maxNumConditions
return numConditions;
}
+const zeroInputTypes: Set = new Set([
+ 'empty',
+ 'notBlank',
+ 'blank',
+ 'today',
+ 'yesterday',
+ 'tomorrow',
+ 'thisWeek',
+ 'lastWeek',
+ 'nextWeek',
+ 'thisMonth',
+ 'lastMonth',
+ 'nextMonth',
+ 'thisQuarter',
+ 'lastQuarter',
+ 'nextQuarter',
+ 'thisYear',
+ 'lastYear',
+ 'nextYear',
+ 'yearToDate',
+ 'last7Days',
+ 'last30Days',
+ 'last90Days',
+ 'last6Months',
+ 'last12Months',
+ 'last24Months',
+]);
+
export function getNumberOfInputs(
type: ISimpleFilterModelType | null | undefined,
optionsFactory: OptionsFactory
@@ -53,9 +81,7 @@ export function getNumberOfInputs(
return numberOfInputs != null ? numberOfInputs : 1;
}
- const zeroInputTypes: ISimpleFilterModelType[] = ['empty', 'notBlank', 'blank'];
-
- if (type && zeroInputTypes.indexOf(type) >= 0) {
+ if (type && zeroInputTypes.has(type)) {
return 0;
} else if (type === 'inRange') {
return 2;
diff --git a/packages/ag-grid-community/src/testing/testIdService.ts b/packages/ag-grid-community/src/testing/testIdService.ts
index a268dbf5c95..9922da3cb11 100644
--- a/packages/ag-grid-community/src/testing/testIdService.ts
+++ b/packages/ag-grid-community/src/testing/testIdService.ts
@@ -409,17 +409,29 @@ export class TestIdService extends BeanStub implements NamedBean, ITestIdService
const filterClass = spec.source === 'floating-filter' ? '.ag-floating-filter-body' : '.ag-filter-body';
- filterRoot.querySelectorAll(`${filterClass} input[type="number"]`).forEach((numberInput, i) => {
- setTestId(numberInput, agTestIdFor.numberFilterInstanceInput({ ...(spec as ColumnFilterSpec), index: i }));
- });
+ filterRoot
+ .querySelectorAll(`${filterClass} .ag-input-field:not(.ag-hidden) input[type="number"]`)
+ .forEach((numberInput, i, array) => {
+ const setIndex = array.length > 1;
+ const filterSpec = setIndex ? { ...(spec as ColumnFilterSpec), index: i } : spec;
+ setTestId(numberInput, agTestIdFor.numberFilterInstanceInput(filterSpec));
+ });
- filterRoot.querySelectorAll(`${filterClass} input[type="text"]`).forEach((textInput, i) => {
- setTestId(textInput, agTestIdFor.textFilterInstanceInput({ ...(spec as ColumnFilterSpec), index: i }));
- });
+ filterRoot
+ .querySelectorAll(`${filterClass} .ag-input-field:not(.ag-hidden) input[type="text"]`)
+ .forEach((textInput, i, array) => {
+ const setIndex = array.length > 1;
+ const filterSpec = setIndex ? { ...(spec as ColumnFilterSpec), index: i } : spec;
+ setTestId(textInput, agTestIdFor.textFilterInstanceInput(filterSpec));
+ });
- filterRoot.querySelectorAll(`${filterClass} input[type="date"]`).forEach((dateInput, i) => {
- setTestId(dateInput, agTestIdFor.dateFilterInstanceInput({ ...(spec as ColumnFilterSpec), index: i }));
- });
+ filterRoot
+ .querySelectorAll(`${filterClass} .ag-input-field:not(.ag-hidden) input[type="date"]`)
+ .forEach((dateInput, i, array) => {
+ const setIndex = array.length > 1;
+ const filterSpec = setIndex ? { ...(spec as ColumnFilterSpec), index: i } : spec;
+ setTestId(dateInput, agTestIdFor.dateFilterInstanceInput(filterSpec));
+ });
const setMiniFilterInput = filterRoot.querySelector('.ag-mini-filter input[type="text"]');
setTestId(setMiniFilterInput, agTestIdFor.setFilterInstanceMiniFilterInput(spec));
diff --git a/packages/ag-grid-community/src/testing/testIdUtils.ts b/packages/ag-grid-community/src/testing/testIdUtils.ts
index 2bcff6043b7..1efd99db7f1 100644
--- a/packages/ag-grid-community/src/testing/testIdUtils.ts
+++ b/packages/ag-grid-community/src/testing/testIdUtils.ts
@@ -14,6 +14,7 @@ function formatTestId(name: string, attributes: Record(fn: (str: string) => TLocator): Locato
return locators as Locators;
};
+
+function mapKeys(obj: Record, keys: Partial>): Record {
+ return Object.fromEntries(
+ Object.entries(obj).reduce(
+ (acc, [k, v]) => {
+ if (keys[k] !== null) {
+ acc.push([keys[k] ?? k, v]);
+ }
+ return acc;
+ },
+ [] as [string, string][]
+ )
+ );
+}
+
+function applySpecDefaults(obj: FilterSpec): FilterSpec {
+ return obj.source !== 'floating-filter' ? { index: 0, ...obj } : obj;
+}
+
+function prepFilterSpec(obj: FilterSpec): Partial> {
+ return mapKeys(applySpecDefaults(obj), { colLabel: 'label' });
+}
diff --git a/testing/behavioural/src/filters/floating-filters.test.ts b/testing/behavioural/src/filters/floating-filters.test.ts
index 42d2fea1059..33495ba5cba 100644
--- a/testing/behavioural/src/filters/floating-filters.test.ts
+++ b/testing/behavioural/src/filters/floating-filters.test.ts
@@ -45,10 +45,12 @@ describe('Floating Filters', () => {
// Wait for next tick, filters are async
await asyncSetTimeout(0);
- const textFilter = getByTestId(
- gridDiv,
- agTestIdFor.textFilterInstanceInput({ source: 'floating-filter', colId: 'country' })
- );
+ const getTestId =
+ filter === 'agNumberColumnFilter'
+ ? agTestIdFor.numberFilterInstanceInput
+ : agTestIdFor.textFilterInstanceInput;
+
+ const textFilter = getByTestId(gridDiv, getTestId({ source: 'floating-filter', colId: 'country' }));
expect(textFilter.getAttribute('placeholder')).toBeNull();
});
@@ -79,10 +81,12 @@ describe('Floating Filters', () => {
// Wait for next tick, filters are async
await asyncSetTimeout(0);
- const textFilter = getByTestId(
- gridDiv,
- agTestIdFor.textFilterInstanceInput({ source: 'floating-filter', colId: 'country' })
- );
+ const getTestId =
+ filter === 'agNumberColumnFilter'
+ ? agTestIdFor.numberFilterInstanceInput
+ : agTestIdFor.textFilterInstanceInput;
+
+ const textFilter = getByTestId(gridDiv, getTestId({ source: 'floating-filter', colId: 'country' }));
expect(textFilter.getAttribute('placeholder')).toBe('type here');
});
@@ -113,10 +117,12 @@ describe('Floating Filters', () => {
// Wait for next tick, filters are async
await asyncSetTimeout(0);
- const textFilter = getByTestId(
- gridDiv,
- agTestIdFor.textFilterInstanceInput({ source: 'floating-filter', colId: 'country' })
- );
+ const getTestId =
+ filter === 'agNumberColumnFilter'
+ ? agTestIdFor.numberFilterInstanceInput
+ : agTestIdFor.textFilterInstanceInput;
+
+ const textFilter = getByTestId(gridDiv, getTestId({ source: 'floating-filter', colId: 'country' }));
expect(textFilter.getAttribute('placeholder')).toBe('Filter...');
});