diff --git a/tests/playwright/pages/Dashboard/Settings/Miscellaneous.ts b/tests/playwright/pages/Dashboard/Settings/Miscellaneous.ts index b2430488d1..75ae679458 100644 --- a/tests/playwright/pages/Dashboard/Settings/Miscellaneous.ts +++ b/tests/playwright/pages/Dashboard/Settings/Miscellaneous.ts @@ -21,4 +21,8 @@ export class MiscSettingsPage extends BasePage { httpMethodsToMatch: ['GET'], }); } + + async clickShowNullEmptyFilters() { + await this.get().locator('input[type="checkbox"]').last().click(); + } } diff --git a/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts b/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts index 192e2fa54f..43470de79d 100644 --- a/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts +++ b/tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts @@ -147,4 +147,30 @@ export class ToolbarFilterPage extends BasePage { }); await this.toolbar.clickFilter(); } + + async columnOperatorList(param: { columnTitle: string }) { + await this.get().locator(`button:has-text("Add Filter")`).first().click(); + + const selectedField = await this.rootPage.locator('.nc-filter-field-select').textContent(); + if (selectedField !== param.columnTitle) { + await this.rootPage.locator('.nc-filter-field-select').last().click(); + await this.rootPage + .locator('div.ant-select-dropdown.nc-dropdown-toolbar-field-list') + .locator(`div[label="${param.columnTitle}"]:visible`) + .click(); + } + + await this.rootPage.locator('.nc-filter-operation-select').click(); + const opList = await this.rootPage + .locator('.nc-dropdown-filter-comp-op') + .locator(`.ant-select-item > .ant-select-item-option-content`); + + // extract text from each element & put them in an array + const opListText = []; + for (let i = 0; i < (await opList.count()); i++) { + opListText.push(await opList.nth(i).textContent()); + } + + return opListText; + } } diff --git a/tests/playwright/tests/filters.spec.ts b/tests/playwright/tests/filters.spec.ts index dcc3043a82..599445b951 100644 --- a/tests/playwright/tests/filters.spec.ts +++ b/tests/playwright/tests/filters.spec.ts @@ -1,10 +1,11 @@ -import { test } from '@playwright/test'; +import { expect, test } from '@playwright/test'; import { DashboardPage } from '../pages/Dashboard'; import setup from '../setup'; import { ToolbarPage } from '../pages/Dashboard/common/Toolbar'; import { UITypes } from 'nocodb-sdk'; import { Api } from 'nocodb-sdk'; import { rowMixedValue } from '../setup/xcdb-records'; +import { SettingsSubTab, SettingTab } from '../pages/Dashboard/Settings'; let dashboard: DashboardPage, toolbar: ToolbarPage; let context: any; @@ -34,6 +35,17 @@ const skipList = { MultiSelect: ['is blank', 'is not blank', 'is', 'is not'], }; +async function verifyFilterOperatorList(param: { column: string; opType: string[] }) { + await toolbar.clickFilter(); + const opList = await toolbar.filter.columnOperatorList({ + columnTitle: param.column, + }); + await toolbar.clickFilter(); + await toolbar.filter.reset(); + + expect(opList).toEqual(param.opType); +} + // define validateRowArray function async function validateRowArray(param) { const { rowCount } = param; @@ -667,3 +679,86 @@ test.describe('Filter Tests: AddOn', () => { await addOnFilterTest('Checkbox'); }); }); + +test.describe('Filter Tests: Toggle button', () => { + /** + * Steps + * + * 1. Open table + * 2. Verify filter options : should not include NULL & EMPTY options + * 3. Enable `Show NULL & EMPTY in Filter` in Project Settings + * 4. Verify filter options : should include NULL & EMPTY options + * 5. Add NULL & EMPTY filters + * 6. Disable `Show NULL & EMPTY in Filter` in Project Settings : should not be allowed + * 7. Remove the NULL & EMPTY filters + * 8. Disable `Show NULL & EMPTY in Filter` in Project Settings again : should be allowed + * + */ + + test.beforeEach(async ({ page }) => { + context = await setup({ page }); + dashboard = new DashboardPage(page, context.project); + toolbar = dashboard.grid.toolbar; + }); + + test('Filter: Toggle NULL & EMPTY button', async () => { + await dashboard.closeTab({ title: 'Team & Auth' }); + await dashboard.treeView.openTable({ title: 'Country' }); + + // Verify filter options + await verifyFilterOperatorList({ + column: 'Country', + opType: ['is equal', 'is not equal', 'is like', 'is not like', 'is blank', 'is not blank'], + }); + + // Enable NULL & EMPTY button + await dashboard.gotoSettings(); + await dashboard.settings.selectTab({ tab: SettingTab.ProjectSettings, subTab: SettingsSubTab.Miscellaneous }); + await dashboard.settings.miscellaneous.clickShowNullEmptyFilters(); + await dashboard.settings.close(); + + // Verify filter options + await verifyFilterOperatorList({ + column: 'Country', + opType: [ + 'is equal', + 'is not equal', + 'is like', + 'is not like', + 'is empty', + 'is not empty', + 'is null', + 'is not null', + 'is blank', + 'is not blank', + ], + }); + + await toolbar.clickFilter(); + await toolbar.filter.add({ + columnTitle: 'Country', + opType: 'is null', + value: null, + isLocallySaved: false, + dataType: 'SingleLineText', + }); + await toolbar.clickFilter(); + + // Disable NULL & EMPTY button + await dashboard.gotoSettings(); + await dashboard.settings.selectTab({ tab: SettingTab.ProjectSettings, subTab: SettingsSubTab.Miscellaneous }); + await dashboard.settings.miscellaneous.clickShowNullEmptyFilters(); + // wait for toast message + await dashboard.verifyToast({ message: 'Null / Empty filters exist. Please remove them first.' }); + await dashboard.settings.close(); + + // remove filter + await toolbar.filter.reset(); + + // Disable NULL & EMPTY button + await dashboard.gotoSettings(); + await dashboard.settings.selectTab({ tab: SettingTab.ProjectSettings, subTab: SettingsSubTab.Miscellaneous }); + await dashboard.settings.miscellaneous.clickShowNullEmptyFilters(); + await dashboard.settings.close(); + }); +});