diff --git a/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts b/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts index 8b8420f00a..896987d26d 100644 --- a/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts +++ b/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts @@ -32,12 +32,14 @@ export class ToolbarFilterPage extends BasePage { async add({ columnTitle, opType, + opSubType, value, isLocallySaved, dataType, }: { columnTitle: string; opType: string; + opSubType?: string; // for date datatype value?: string; isLocallySaved: boolean; dataType?: string; @@ -53,19 +55,6 @@ export class ToolbarFilterPage extends BasePage { .click(); } - // network request will be triggered only after filter value is configured - // - // const selectColumn = this.rootPage - // .locator('div.ant-select-dropdown.nc-dropdown-toolbar-field-list') - // .locator(`div[label="${columnTitle}"]`) - // .click(); - // await this.waitForResponse({ - // uiAction: selectColumn, - // httpMethodsToMatch: isLocallySaved ? ['GET'] : ['POST', 'PATCH'], - // requestUrlPathToMatch: isLocallySaved ? `/api/v1/db/public/` : `/filters`, - // }); - // await this.toolbar.parent.dashboard.waitForLoaderToDisappear(); - const selectedOpType = await this.rootPage.locator('.nc-filter-operation-select').textContent(); if (selectedOpType !== opType) { await this.rootPage.locator('.nc-filter-operation-select').click(); @@ -76,22 +65,20 @@ export class ToolbarFilterPage extends BasePage { .first() .click(); } - // if (selectedOpType !== opType) { - // await this.rootPage.locator('.nc-filter-operation-select').last().click(); - // // first() : filter list has >, >= - // const selectOpType = this.rootPage - // .locator('.nc-dropdown-filter-comp-op') - // .locator(`.ant-select-item:has-text("${opType}")`) - // .first() - // .click(); - // - // await this.waitForResponse({ - // uiAction: selectOpType, - // httpMethodsToMatch: isLocallySaved ? ['GET'] : ['POST', 'PATCH'], - // requestUrlPathToMatch: isLocallySaved ? `/api/v1/db/public/` : `/filters`, - // }); - // await this.toolbar.parent.dashboard.waitForLoaderToDisappear(); - // } + + // subtype for date + if (dataType === UITypes.Date && opSubType) { + const selectedSubType = await this.rootPage.locator('.nc-filter-sub_operation-select').textContent(); + if (selectedSubType !== opSubType) { + await this.rootPage.locator('.nc-filter-sub_operation-select').click(); + // first() : filter list has >, >= + await this.rootPage + .locator('.nc-dropdown-filter-comp-sub-op') + .locator(`.ant-select-item:has-text("${opSubType}")`) + .first() + .click(); + } + } // if value field was provided, fill it if (value) { diff --git a/tests/playwright/setup/xcdb-records.ts b/tests/playwright/setup/xcdb-records.ts index 4edd3df393..419e4dc442 100644 --- a/tests/playwright/setup/xcdb-records.ts +++ b/tests/playwright/setup/xcdb-records.ts @@ -120,7 +120,11 @@ const rowMixedValue = (column: ColumnType, index: number) => { case UITypes.LongText: return longText[index % longText.length]; case UITypes.Date: - return '2020-01-01'; + // set startDate as 400 days before today + // eslint-disable-next-line no-case-declarations + const result = new Date(); + result.setDate(result.getDate() - 400 + index); + return result; case UITypes.URL: return urls[index % urls.length]; case UITypes.SingleSelect: diff --git a/tests/playwright/tests/filters.spec.ts b/tests/playwright/tests/filters.spec.ts index c50ae29ac6..bccc04e4bd 100644 --- a/tests/playwright/tests/filters.spec.ts +++ b/tests/playwright/tests/filters.spec.ts @@ -47,6 +47,7 @@ async function validateRowArray(param) { async function verifyFilter(param: { column: string; opType: string; + opSubType?: string; value?: string; result: { rowCount: number }; dataType?: string; @@ -60,6 +61,7 @@ async function verifyFilter(param: { await toolbar.filter.add({ columnTitle: param.column, opType: param.opType, + opSubType: param.opSubType, value: param.value, isLocallySaved: false, dataType: param?.dataType, @@ -591,6 +593,145 @@ test.describe('Filter Tests: Select based', () => { }); }); +// Date & Time related +// + +test.describe.skip('Filter Tests: Date & Time related', () => { + async function dateTimeBasedFilterTest(dataType) { + await dashboard.closeTab({ title: 'Team & Auth' }); + await dashboard.treeView.openTable({ title: 'dateTimeBased' }); + + // Enable NULL & EMPTY filters + await dashboard.gotoSettings(); + await dashboard.settings.toggleNullEmptyFilters(); + + // store date in YYYY-MM-DD format + const today = new Date().toISOString().split('T')[0]; + const tomorrow = new Date(new Date().setDate(new Date().getDate() + 1)).toISOString().split('T')[0]; + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)).toISOString().split('T')[0]; + const oneWeekAgo = new Date(new Date().setDate(new Date().getDate() - 7)).toISOString().split('T')[0]; + const oneWeekFromNow = new Date(new Date().setDate(new Date().getDate() + 7)).toISOString().split('T')[0]; + const oneMonthAgo = new Date(new Date().setMonth(new Date().getMonth() - 1)).toISOString().split('T')[0]; + const oneMonthFromNow = new Date(new Date().setMonth(new Date().getMonth() + 1)).toISOString().split('T')[0]; + const daysAgo45 = new Date(new Date().setDate(new Date().getDate() + 45)).toISOString().split('T')[0]; + const daysFromNow45 = new Date(new Date().setDate(new Date().getDate() - 45)).toISOString().split('T')[0]; + + console.log(today); + + const filterList = [ + { + op: 'is', + opSub: 'today', + rowCount: records.list.filter(r => r[dataType].split('T')[0] === today).length, + }, + { + op: 'is', + opSub: 'tomorrow', + rowCount: records.list.filter(r => r[dataType].split('T')[0] === tomorrow).length, + }, + { + op: 'is', + opSub: 'yesterday', + rowCount: records.list.filter(r => r[dataType].split('T')[0] === yesterday).length, + }, + { + op: 'is', + opSub: 'one week ago', + rowCount: records.list.filter(r => r[dataType].split('T')[0] === oneWeekAgo).length, + }, + { + op: 'is', + opSub: 'one week from now', + rowCount: records.list.filter(r => r[dataType].split('T')[0] === oneWeekFromNow).length, + }, + { + op: 'is', + opSub: 'one month ago', + rowCount: records.list.filter(r => r[dataType].split('T')[0] === oneMonthAgo).length, + }, + { + op: 'is', + opSub: 'one month from now', + rowCount: records.list.filter(r => r[dataType].split('T')[0] === oneMonthFromNow).length, + }, + { + op: 'is', + opSub: 'number of days ago', + value: 45, + rowCount: records.list.filter(r => r[dataType].split('T')[0] === daysAgo45).length, + }, + { + op: 'is', + opSub: 'number of days from now', + value: 45, + rowCount: records.list.filter(r => r[dataType].split('T')[0] === daysFromNow45).length, + }, + ]; + + for (let i = 0; i < filterList.length; i++) { + await verifyFilter({ + column: dataType, + opType: filterList[i].op, + opSubType: filterList[i].opSub, + value: filterList[i]?.value?.toString() || '', + result: { rowCount: filterList[i].rowCount }, + dataType: dataType, + }); + } + } + test.beforeEach(async ({ page }) => { + context = await setup({ page }); + dashboard = new DashboardPage(page, context.project); + toolbar = dashboard.grid.toolbar; + + api = new Api({ + baseURL: `http://localhost:8080/`, + headers: { + 'xc-auth': context.token, + }, + }); + + const columns = [ + { + column_name: 'Id', + title: 'Id', + uidt: UITypes.ID, + }, + { + column_name: 'Date', + title: 'Date', + uidt: UITypes.Date, + }, + ]; + + try { + const project = await api.project.read(context.project.id); + const table = await api.base.tableCreate(context.project.id, project.bases?.[0].id, { + table_name: 'dateTimeBased', + title: 'dateTimeBased', + columns: columns, + }); + + const rowAttributes = []; + for (let i = 0; i < 800; i++) { + const row = { + Date: rowMixedValue(columns[1], i), + }; + rowAttributes.push(row); + } + + await api.dbTableRow.bulkCreate('noco', context.project.id, table.id, rowAttributes); + records = await api.dbTableRow.list('noco', context.project.id, table.id, { limit: 800 }); + } catch (e) { + console.error(e); + } + }); + + test('Date', async () => { + await dateTimeBasedFilterTest('Date'); + }); +}); + // Misc : Checkbox //