Browse Source

Merge branch 'develop' into refactor/webhooks

pull/5349/head
Wing-Kam Wong 2 years ago
parent
commit
37de973c0d
  1. 2
      packages/nc-gui/components/virtual-cell/components/ItemChip.vue
  2. 3
      tests/playwright/pages/Account/Users.ts
  3. 10
      tests/playwright/pages/Dashboard/Grid/Column/SelectOptionColumn.ts
  4. 30
      tests/playwright/pages/Dashboard/Grid/Column/index.ts
  5. 8
      tests/playwright/pages/Dashboard/Import/ImportTemplate.ts
  6. 11
      tests/playwright/pages/Dashboard/Settings/Metadata.ts
  7. 3
      tests/playwright/pages/Dashboard/Settings/Teams.ts
  8. 14
      tests/playwright/pages/Dashboard/SurveyForm/index.ts
  9. 2
      tests/playwright/pages/Dashboard/TreeView.ts
  10. 7
      tests/playwright/pages/Dashboard/ViewSidebar/index.ts
  11. 9
      tests/playwright/pages/Dashboard/WebhookForm/index.ts
  12. 3
      tests/playwright/pages/Dashboard/common/Cell/index.ts
  13. 4
      tests/playwright/pages/Dashboard/common/Toolbar/Actions/index.ts
  14. 6
      tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts
  15. 5
      tests/playwright/pages/Dashboard/common/Toolbar/ShareView.ts
  16. 6
      tests/playwright/pages/Dashboard/common/Toolbar/Sort.ts
  17. 6
      tests/playwright/pages/Dashboard/common/Toolbar/ViewMenu.ts
  18. 21
      tests/playwright/pages/Dashboard/common/Toolbar/index.ts
  19. 5
      tests/playwright/tests/columnLinkToAnotherRecord.spec.ts
  20. 1
      tests/playwright/tests/columnMenuOperations.spec.ts
  21. 188
      tests/playwright/tests/filters.spec.ts
  22. 2
      tests/playwright/tests/metaSync.spec.ts
  23. 2
      tests/playwright/tests/rolesPreview.spec.ts
  24. 22
      tests/playwright/tests/utils/general.ts

2
packages/nc-gui/components/virtual-cell/components/ItemChip.vue

@ -65,7 +65,7 @@ export default {
<div v-show="active || isForm" v-if="!readOnly && !isLocked && isUIAllowed('xcDatatableEditable')" class="flex items-center">
<component
:is="iconMap.closeThick"
class="unlink-icon text-xs text-gray-500/50 group-hover:text-gray-500"
class="nc-icon unlink-icon text-xs text-gray-500/50 group-hover:text-gray-500"
@click.stop="emit('unlink')"
/>
</div>

3
tests/playwright/pages/Account/Users.ts

@ -36,7 +36,8 @@ export class AccountUsersPage extends BasePage {
await this.inviteUserModal.locator(`button:has-text("Invite")`).click();
await this.verifyToast({ message: 'Successfully added user' });
return await this.inviteUserModal.locator(`.ant-alert-message`).innerText();
// http://localhost:3000/#/signup/a5e7bf3a-cbb0-46bc-87f7-c2ae21796707
return (await this.inviteUserModal.locator(`.ant-alert-message`).innerText()).slice(0, 67);
}
prefixEmail(email: string) {

10
tests/playwright/pages/Dashboard/Grid/Column/SelectOptionColumn.ts

@ -60,7 +60,7 @@ export class SelectOptionColumnPageObject extends BasePage {
async deleteOption({ columnTitle, index }: { index: number; columnTitle: string }) {
await this.column.openEdit({ title: columnTitle });
await this.column.get().locator(`svg[data-testid="select-column-option-remove-${index}"]`).click();
await this.column.get().locator(`[data-testid="select-column-option-remove-${index}"]`).click();
await expect(this.column.get().getByTestId(`select-column-option-${index}`)).toHaveClass(/removed/);
@ -70,11 +70,11 @@ export class SelectOptionColumnPageObject extends BasePage {
async deleteOptionWithUndo({ columnTitle, index }: { index: number; columnTitle: string }) {
await this.column.openEdit({ title: columnTitle });
await this.column.get().locator(`svg[data-testid="select-column-option-remove-${index}"]`).click();
await this.column.get().locator(`[data-testid="select-column-option-remove-${index}"]`).click();
await expect(this.column.get().getByTestId(`select-column-option-${index}`)).toHaveClass(/removed/);
await this.column.get().locator(`svg[data-testid="select-column-option-remove-undo-${index}"]`).click();
await this.column.get().locator(`[data-testid="select-column-option-remove-undo-${index}"]`).click();
await expect(this.column.get().getByTestId(`select-column-option-${index}`)).not.toHaveClass(/removed/);
@ -95,8 +95,8 @@ export class SelectOptionColumnPageObject extends BasePage {
await this.column.rootPage.waitForTimeout(150);
await this.column.rootPage.dragAndDrop(
`svg[data-testid="select-option-column-handle-icon-${sourceOption}"]`,
`svg[data-testid="select-option-column-handle-icon-${destinationOption}"]`,
`[data-testid="select-option-column-handle-icon-${sourceOption}"]`,
`[data-testid="select-option-column-handle-icon-${destinationOption}"]`,
{
force: true,
}

30
tests/playwright/pages/Dashboard/Grid/Column/index.ts

@ -3,6 +3,7 @@ import { GridPage } from '..';
import BasePage from '../../../Base';
import { SelectOptionColumnPageObject } from './SelectOptionColumn';
import { AttachmentColumnPageObject } from './Attachment';
import { getTextExcludeIconText } from '../../../../tests/utils/general';
export class ColumnPageObject extends BasePage {
readonly grid: GridPage;
@ -181,28 +182,23 @@ export class ColumnPageObject extends BasePage {
await this.save();
const headersText = [];
const locator = this.grid.get().locator(`th`);
const count = await locator.count();
for (let i = 0; i < count; i++) {
const header = locator.nth(i);
const text = await getTextExcludeIconText(header);
headersText.push(text);
}
// verify column inserted after the target column
if (insertAfterColumnTitle) {
const headersText = await this.grid.get().locator(`th`).allTextContents();
await expect(
this.grid
.get()
.locator(`th`)
.nth(headersText.findIndex(title => title.startsWith(insertAfterColumnTitle)) + 1)
).toHaveText(title);
expect(headersText[headersText.findIndex(title => title.startsWith(insertAfterColumnTitle)) + 1]).toBe(title);
}
// verify column inserted before the target column
if (insertBeforeColumnTitle) {
const headersText = await this.grid.get().locator(`th`).allTextContents();
await expect(
this.grid
.get()
.locator(`th`)
.nth(headersText.findIndex(title => title.startsWith(insertBeforeColumnTitle)) - 1)
).toHaveText(title);
expect(headersText[headersText.findIndex(title => title.startsWith(insertBeforeColumnTitle)) - 1]).toBe(title);
}
}
@ -254,7 +250,7 @@ export class ColumnPageObject extends BasePage {
}
async delete({ title }: { title: string }) {
await this.getColumnHeader(title).locator('svg.ant-dropdown-trigger').click();
await this.getColumnHeader(title).locator('div.ant-dropdown-trigger').locator('.nc-ui-dt-dropdown').click();
// await this.rootPage.locator('li[role="menuitem"]:has-text("Delete")').waitFor();
await this.rootPage.locator('li[role="menuitem"]:has-text("Delete")').click();

8
tests/playwright/pages/Dashboard/Import/ImportTemplate.ts

@ -1,6 +1,7 @@
import { expect, Locator } from '@playwright/test';
import BasePage from '../../Base';
import { DashboardPage } from '..';
import { getTextExcludeIconText } from '../../../tests/utils/general';
export class ImportTemplatePage extends BasePage {
readonly dashboard: DashboardPage;
@ -22,7 +23,7 @@ export class ImportTemplatePage extends BasePage {
const rowCount = await tr.count();
const tableList: string[] = [];
for (let i = 0; i < rowCount; i++) {
const tableName = await tr.nth(i).innerText();
const tableName = await getTextExcludeIconText(tr.nth(i));
tableList.push(tableName);
}
return tableList;
@ -35,10 +36,7 @@ export class ImportTemplatePage extends BasePage {
const rowCount = await tr.count();
for (let i = 0; i < rowCount; i++) {
// replace \n and \t from innerText
const columnType = await tr
.nth(i)
.innerText()
.then(text => text.replace(/\n|\t/g, ''));
const columnType = (await getTextExcludeIconText(tr.nth(i))).replace(/\n|\t/g, '');
const columnName = await tr.nth(i).locator(`input[type="text"]`).inputValue();
columnList.push({ type: columnType, name: columnName });
}

11
tests/playwright/pages/Dashboard/Settings/Metadata.ts

@ -1,6 +1,7 @@
import { expect } from '@playwright/test';
import BasePage from '../../Base';
import { DataSourcesPage } from './DataSources';
import { getTextExcludeIconText } from '../../../tests/utils/general';
export class MetaDataPage extends BasePage {
private readonly dataSources: DataSourcesPage;
@ -31,12 +32,10 @@ export class MetaDataPage extends BasePage {
}
async verifyRow({ index, model, state }: { index: number; model: string; state: string }) {
await expect(this.get().locator(`tr.ant-table-row`).nth(index).locator(`td.ant-table-cell`).nth(0)).toHaveText(
model,
{
ignoreCase: true,
}
);
const fieldLocator = await this.get().locator(`tr.ant-table-row`).nth(index).locator(`td.ant-table-cell`).nth(0);
const fieldText = await getTextExcludeIconText(fieldLocator);
await expect(fieldText).toBe(model);
await expect(this.get().locator(`tr.ant-table-row`).nth(index).locator(`td.ant-table-cell`).nth(1)).toHaveText(
state,
{

3
tests/playwright/pages/Dashboard/Settings/Teams.ts

@ -44,7 +44,8 @@ export class TeamsPage extends BasePage {
await this.inviteTeamModal.locator(`button:has-text("Invite")`).click();
await this.verifyToast({ message: 'Successfully updated the user details' });
return await this.inviteTeamModal.locator(`.ant-alert-message`).innerText();
// http://localhost:3000/#/signup/a5e7bf3a-cbb0-46bc-87f7-c2ae21796707
return (await this.inviteTeamModal.locator(`.ant-alert-message`).innerText()).slice(0, 67);
}
async closeInvite() {

14
tests/playwright/pages/Dashboard/SurveyForm/index.ts

@ -1,5 +1,6 @@
import { expect, Locator, Page } from '@playwright/test';
import BasePage from '../../Base';
import { getTextExcludeIconText } from '../../../tests/utils/general';
export class SurveyFormPage extends BasePage {
readonly formHeading: Locator;
@ -42,7 +43,15 @@ export class SurveyFormPage extends BasePage {
await expect(this.formHeading).toHaveText(heading);
await expect(this.formSubHeading).toHaveText(subHeading);
await expect(this.formFooter).toHaveText(footer);
await expect(this.get().locator(`[data-testid="nc-form-column-label"]`)).toHaveText(fieldLabel);
const locator = this.get().locator(`[data-testid="nc-form-column-label"]`);
let fieldText = await getTextExcludeIconText(locator);
// replace whitespace with ' ' for fieldLabel & fieldText
fieldLabel = fieldLabel.replace(/\u00A0/g, ' ');
fieldText = fieldText.replace(/\u00A0/g, ' ');
await expect(fieldText).toBe(fieldLabel);
// parse footer text ("1 / 3") to identify if last slide
let isLastSlide = false;
@ -73,6 +82,9 @@ export class SurveyFormPage extends BasePage {
await modal.locator('.ant-picker-ok').click();
await this.nextButton.click();
}
// post next button click, allow transitions to complete
await this.rootPage.waitForTimeout(100);
}
async validateSuccessMessage(param: { message: string; showAnotherForm?: boolean }) {

2
tests/playwright/pages/Dashboard/TreeView.ts

@ -39,7 +39,7 @@ export class TreeViewPage extends BasePage {
async openTable({
title,
mode = 'standard',
networkResponse = true,
networkResponse = false,
mobileMode = false,
}: {
title: string;

7
tests/playwright/pages/Dashboard/ViewSidebar/index.ts

@ -86,6 +86,13 @@ export class ViewSidebarPage extends BasePage {
// Todo: Make selection better
async verifyView({ title, index }: { title: string; index: number }) {
// flicker while page loading
await this.get()
.locator('[data-testid="view-item"]')
.nth(index)
.locator('[data-testid="truncate-label"]')
.waitFor({ state: 'visible' });
await expect(
this.get().locator('[data-testid="view-item"]').nth(index).locator('[data-testid="truncate-label"]')
).toHaveText(title, { ignoreCase: true });

9
tests/playwright/pages/Dashboard/WebhookForm/index.ts

@ -2,6 +2,7 @@ import { expect, Locator } from '@playwright/test';
import BasePage from '../../Base';
import { DashboardPage } from '..';
import { ToolbarPage } from '../common/Toolbar';
import { getTextExcludeIconText } from '../../../tests/utils/general';
export class WebhookFormPage extends BasePage {
readonly dashboard: DashboardPage;
@ -181,9 +182,11 @@ export class WebhookFormPage extends BasePage {
}) {
await expect.poll(async () => await this.get().locator('input.nc-text-field-hook-title').inputValue()).toBe(title);
await expect(this.get().locator('.nc-text-field-hook-event >> .ant-select-selection-item')).toHaveText(hookEvent);
await expect(this.get().locator('.nc-select-hook-notification-type >> .ant-select-selection-item')).toHaveText(
notificationType
);
const locator = this.get().locator('.nc-select-hook-notification-type >> .ant-select-selection-item');
const text = await getTextExcludeIconText(locator);
await expect(text).toBe(notificationType);
await expect(this.get().locator('.nc-select-hook-url-method >> .ant-select-selection-item')).toHaveText(urlMethod);
await expect.poll(async () => await this.get().locator('input.nc-text-field-hook-url-path').inputValue()).toBe(url);

3
tests/playwright/pages/Dashboard/common/Cell/index.ts

@ -273,7 +273,7 @@ export class CellPageObject extends BasePage {
// verify only the elements that are passed in
for (let i = 0; i < value.length; ++i) {
await expect(await chips.nth(i)).toHaveText(value[i]);
await expect(await chips.nth(i).locator('.name')).toHaveText(value[i]);
}
}
@ -292,6 +292,7 @@ export class CellPageObject extends BasePage {
// press escape to close the input
await cell.press('Escape');
await cell.press('Escape');
await cell.click({ button: 'right', clickCount: 1 });
await expect(await this.rootPage.locator(`.nc-dropdown-grid-context-menu:visible`)).toHaveCount(

4
tests/playwright/pages/Dashboard/common/Toolbar/Actions/index.ts

@ -18,10 +18,10 @@ export class ToolbarActionsPage extends BasePage {
// todo: use enum
async click(label: string) {
await this.get().locator(`span:has-text("${label}")`).click();
await this.get().locator(`span:has-text("${label}")`).first().click();
}
async clickDownloadSubmenu(label: string) {
await this.rootPage.locator(`div[class="nc-project-menu-item"]:has-text("${label}")`).click();
await this.rootPage.locator(`div[class="nc-project-menu-item"]:has-text("${label}")`).first().click();
}
}

6
tests/playwright/pages/Dashboard/common/Toolbar/Filter.ts

@ -2,6 +2,7 @@ import { expect } from '@playwright/test';
import BasePage from '../../../Base';
import { ToolbarPage } from './index';
import { UITypes } from 'nocodb-sdk';
import { getTextExcludeIconText } from '../../../../tests/utils/general';
export class ToolbarFilterPage extends BasePage {
readonly toolbar: ToolbarPage;
@ -16,7 +17,10 @@ export class ToolbarFilterPage extends BasePage {
}
async verify({ index, column, operator, value }: { index: number; column: string; operator: string; value: string }) {
await expect(this.get().locator('.nc-filter-field-select').nth(index)).toHaveText(column);
const fieldLocator = await this.get().locator('.nc-filter-field-select').nth(index);
const fieldText = await getTextExcludeIconText(fieldLocator);
await expect(fieldText).toBe(column);
await expect(this.get().locator('.nc-filter-operation-select').nth(index)).toHaveText(operator);
await expect
.poll(async () => await this.get().locator('.nc-filter-value-select > input').nth(index).inputValue())

5
tests/playwright/pages/Dashboard/common/Toolbar/ShareView.ts

@ -1,5 +1,6 @@
import BasePage from '../../../Base';
import { ToolbarPage } from './index';
import { getTextExcludeIconText } from '../../../../tests/utils/general';
export class ToolbarShareViewPage extends BasePage {
readonly toolbar: ToolbarPage;
@ -29,7 +30,9 @@ export class ToolbarShareViewPage extends BasePage {
}
async getShareLink() {
return await this.get().locator(`[data-testid="nc-modal-share-view__link"]`).innerText();
const locator = this.get().locator(`[data-testid="nc-modal-share-view__link"]`);
const linkText = getTextExcludeIconText(locator);
return linkText;
}
async close() {

6
tests/playwright/pages/Dashboard/common/Toolbar/Sort.ts

@ -1,6 +1,7 @@
import { expect } from '@playwright/test';
import BasePage from '../../../Base';
import { ToolbarPage } from './index';
import { getTextExcludeIconText } from '../../../../tests/utils/general';
export class ToolbarSortPage extends BasePage {
readonly toolbar: ToolbarPage;
@ -15,7 +16,10 @@ export class ToolbarSortPage extends BasePage {
}
async verify({ index, column, direction }: { index: number; column: string; direction: string }) {
await expect(this.get().locator('.nc-sort-field-select').nth(index)).toHaveText(column);
const fieldLocator = await this.get().locator('.nc-sort-field-select').nth(index);
const fieldText = await getTextExcludeIconText(fieldLocator);
await expect(fieldText).toBe(column);
await expect(
await this.get().locator('.nc-sort-dir-select >> span.ant-select-selection-item').nth(index)
).toHaveText(direction);

6
tests/playwright/pages/Dashboard/common/Toolbar/ViewMenu.ts

@ -141,7 +141,7 @@ export class ToolbarViewMenuPage extends BasePage {
await expect(await this.toolbar.get().locator(`.nc-filter-menu-btn.nc-toolbar-btn`)).toBeDisabled();
await expect(await this.toolbar.get().locator(`.nc-sort-menu-btn.nc-toolbar-btn`)).toBeDisabled();
await expect(
await this.toolbar.get().locator(`.nc-add-new-row-btn.nc-toolbar-btn > .nc-icon.disabled`)
await this.toolbar.get().locator(`.nc-add-new-row-btn.nc-toolbar-btn > .material-symbols-outlined.disabled`)
).toBeVisible();
await (this.toolbar.parent as GridPage).verifyEditDisabled({
@ -153,7 +153,9 @@ export class ToolbarViewMenuPage extends BasePage {
await expect(await this.toolbar.get().locator(`.nc-fields-menu-btn.nc-toolbar-btn`)).toBeEnabled();
await expect(await this.toolbar.get().locator(`.nc-filter-menu-btn.nc-toolbar-btn`)).toBeEnabled();
await expect(await this.toolbar.get().locator(`.nc-sort-menu-btn.nc-toolbar-btn`)).toBeEnabled();
await expect(await this.toolbar.get().locator(`.nc-add-new-row-btn.nc-toolbar-btn > .nc-icon`)).toBeVisible();
await expect(
await this.toolbar.get().locator(`.nc-add-new-row-btn.nc-toolbar-btn > .material-symbols-outlined`)
).toBeVisible();
await (this.toolbar.parent as GridPage).verifyEditEnabled({
columnHeader: 'Country',

21
tests/playwright/pages/Dashboard/common/Toolbar/index.ts

@ -16,6 +16,7 @@ import { ToolbarAddEditStackPage } from './AddEditKanbanStack';
import { ToolbarSearchDataPage } from './SearchData';
import { RowHeight } from './RowHeight';
import { MapPage } from '../../Map';
import { getTextExcludeIconText } from '../../../../tests/utils/general';
export class ToolbarPage extends BasePage {
readonly parent: GridPage | GalleryPage | FormPage | KanbanPage | MapPage;
@ -82,14 +83,26 @@ export class ToolbarPage extends BasePage {
async verifyFieldsButtonIsVisibleWithTextAndIcon() {
await expect(this.get().locator(`button.nc-fields-menu-btn`)).toBeVisible();
await expect(this.get().locator(`button.nc-fields-menu-btn`)).toHaveText('Fields');
expect(await this.get().locator(`button.nc-fields-menu-btn`).locator(`svg`).count()).toBe(2);
// menu text
const fieldLocator = await this.get().locator(`button.nc-fields-menu-btn`);
const fieldText = await getTextExcludeIconText(fieldLocator);
await expect(fieldText).toBe('Fields');
// icons count within fields menu button
expect(await this.get().locator(`button.nc-fields-menu-btn`).locator(`.material-symbols-outlined`).count()).toBe(2);
}
async verifyFieldsButtonIsVisibleWithoutTextButIcon() {
await expect(this.get().locator(`button.nc-fields-menu-btn`)).toBeVisible();
await expect(this.get().locator(`button.nc-fields-menu-btn`)).not.toHaveText('Fields');
expect(await this.get().locator(`button.nc-fields-menu-btn`).locator(`svg`).count()).toBe(2);
// menu text
const fieldLocator = await this.get().locator(`button.nc-fields-menu-btn`);
const fieldText = await getTextExcludeIconText(fieldLocator);
await expect(fieldText).not.toBe('Fields');
// icons count within fields menu button
expect(await this.get().locator(`button.nc-fields-menu-btn`).locator(`.material-symbols-outlined`).count()).toBe(2);
}
async clickFilter({

5
tests/playwright/tests/columnLinkToAnotherRecord.spec.ts

@ -43,7 +43,7 @@ test.describe('LTAR create & update', () => {
});
await dashboard.closeTab({ title: 'Sheet1' });
await dashboard.treeView.openTable({ title: 'Sheet2' });
await dashboard.treeView.openTable({ title: 'Sheet2', networkResponse: false });
await dashboard.grid.column.create({
title: 'Link2-1hm',
type: 'LinkToAnotherRecord',
@ -116,6 +116,9 @@ test.describe('LTAR create & update', () => {
value: '2c',
type: 'text',
});
await dashboard.rootPage.waitForTimeout(1000);
await dashboard.expandedForm.save();
const expected = [

1
tests/playwright/tests/columnMenuOperations.spec.ts

@ -66,6 +66,7 @@ test.describe('Column menu operations', () => {
}
await dashboard.closeTab({ title: 'Film' });
});
test('Insert after', async () => {
await dashboard.treeView.openTable({ title: 'Film' });

188
tests/playwright/tests/filters.spec.ts

@ -668,7 +668,7 @@ test.describe('Filter Tests: Date based', () => {
const oneYearAgo = new Date(new Date().setFullYear(new Date().getFullYear() - 1)).setHours(0, 0, 0, 0);
const oneYearFromNow = new Date(new Date().setFullYear(new Date().getFullYear() + 1)).setHours(0, 0, 0, 0);
async function dateTimeBasedFilterTest(dataType) {
async function dateTimeBasedFilterTest(dataType, setCount) {
await dashboard.closeTab({ title: 'Team & Auth' });
await dashboard.treeView.openTable({ title: 'dateTimeBased' });
@ -829,100 +829,102 @@ test.describe('Filter Tests: Date based', () => {
await toolbar.clickFilter();
await toolbar.filter.clickAddFilter();
// "is" filter list
for (let i = 0; i < isFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is',
opSubType: isFilterList[i].opSub,
value: isFilterList[i]?.value?.toString() || '',
result: { rowCount: isFilterList[i].rowCount },
dataType: dataType,
});
}
// mutually exclusive of "is" filter list
for (let i = 0; i < isFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is not',
opSubType: isFilterList[i].opSub,
value: isFilterList[i]?.value?.toString() || '',
result: { rowCount: 800 - isFilterList[i].rowCount },
dataType: dataType,
});
}
if (setCount === 0) {
// "is" filter list
for (let i = 0; i < isFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is',
opSubType: isFilterList[i].opSub,
value: isFilterList[i]?.value?.toString() || '',
result: { rowCount: isFilterList[i].rowCount },
dataType: dataType,
});
}
// "is before" filter list
for (let i = 0; i < isAfterFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is before',
opSubType: isAfterFilterList[i].opSub,
value: isAfterFilterList[i]?.value?.toString() || '',
result: { rowCount: 800 - isAfterFilterList[i].rowCount - 1 },
dataType: dataType,
});
}
// mutually exclusive of "is" filter list
for (let i = 0; i < isFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is not',
opSubType: isFilterList[i].opSub,
value: isFilterList[i]?.value?.toString() || '',
result: { rowCount: 800 - isFilterList[i].rowCount },
dataType: dataType,
});
}
// "is on or before" filter list
for (let i = 0; i < isAfterFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is on or before',
opSubType: isAfterFilterList[i].opSub,
value: isAfterFilterList[i]?.value?.toString() || '',
result: { rowCount: 800 - isAfterFilterList[i].rowCount },
dataType: dataType,
});
}
// "is before" filter list
for (let i = 0; i < isAfterFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is before',
opSubType: isAfterFilterList[i].opSub,
value: isAfterFilterList[i]?.value?.toString() || '',
result: { rowCount: 800 - isAfterFilterList[i].rowCount - 1 },
dataType: dataType,
});
}
} else {
// "is on or before" filter list
for (let i = 0; i < isAfterFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is on or before',
opSubType: isAfterFilterList[i].opSub,
value: isAfterFilterList[i]?.value?.toString() || '',
result: { rowCount: 800 - isAfterFilterList[i].rowCount },
dataType: dataType,
});
}
// "is after" filter list
for (let i = 0; i < isAfterFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is after',
opSubType: isAfterFilterList[i].opSub,
value: isAfterFilterList[i]?.value?.toString() || '',
result: { rowCount: isAfterFilterList[i].rowCount },
dataType: dataType,
});
}
// "is after" filter list
for (let i = 0; i < isAfterFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is after',
opSubType: isAfterFilterList[i].opSub,
value: isAfterFilterList[i]?.value?.toString() || '',
result: { rowCount: isAfterFilterList[i].rowCount },
dataType: dataType,
});
}
// "is on or after" filter list
for (let i = 0; i < isAfterFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is on or after',
opSubType: isAfterFilterList[i].opSub,
value: isAfterFilterList[i]?.value?.toString() || '',
result: { rowCount: 1 + isAfterFilterList[i].rowCount },
dataType: dataType,
});
}
// "is on or after" filter list
for (let i = 0; i < isAfterFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is on or after',
opSubType: isAfterFilterList[i].opSub,
value: isAfterFilterList[i]?.value?.toString() || '',
result: { rowCount: 1 + isAfterFilterList[i].rowCount },
dataType: dataType,
});
}
// "is within" filter list
for (let i = 0; i < isWithinFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is within',
opSubType: isWithinFilterList[i].opSub,
value: isWithinFilterList[i]?.value?.toString() || '',
result: { rowCount: isWithinFilterList[i].rowCount },
dataType: dataType,
});
}
// "is within" filter list
for (let i = 0; i < isWithinFilterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: 'is within',
opSubType: isWithinFilterList[i].opSub,
value: isWithinFilterList[i]?.value?.toString() || '',
result: { rowCount: isWithinFilterList[i].rowCount },
dataType: dataType,
});
}
// "is blank" and "is not blank" filter list
for (let i = 0; i < filterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: filterList[i].opType,
opSubType: null,
value: null,
result: { rowCount: filterList[i].rowCount },
dataType: dataType,
});
// "is blank" and "is not blank" filter list
for (let i = 0; i < filterList.length; i++) {
await verifyFilter_withFixedModal({
column: dataType,
opType: filterList[i].opType,
opSubType: null,
value: null,
result: { rowCount: filterList[i].rowCount },
dataType: dataType,
});
}
}
}
@ -974,8 +976,12 @@ test.describe('Filter Tests: Date based', () => {
}
});
test('Date : filters', async () => {
await dateTimeBasedFilterTest('Date');
test('Date : filters-1', async () => {
await dateTimeBasedFilterTest('Date', 1);
});
test('Date : filters-2', async () => {
await dateTimeBasedFilterTest('Date', 2);
});
});

2
tests/playwright/tests/metaSync.spec.ts

@ -39,6 +39,8 @@ test.describe('Meta sync', () => {
await dbExec(`CREATE TABLE table2 (id INT NOT NULL, col1 INT NULL, PRIMARY KEY (id))`);
await settings.dataSources.metaData.clickReload();
await dashboard.rootPage.waitForTimeout(1000);
await settings.dataSources.metaData.verifyRow({
index: isPg(context) ? 21 : 16,
model: `table1`,

2
tests/playwright/tests/rolesPreview.spec.ts

@ -66,7 +66,7 @@ test.describe('Preview Mode', () => {
await dashboard.rootPage.waitForTimeout(1500);
await dashboard.treeView.openTable({ title: 'Country' });
await dashboard.treeView.openTable({ title: 'Country', networkResponse: false });
await dashboard.viewSidebar.validateRoleAccess({
role: role.toLowerCase(),

22
tests/playwright/tests/utils/general.ts

@ -0,0 +1,22 @@
// Selector objects include the text of any icons in the textContent property.
// This function removes the text of any icons from the textContent property.
async function getTextExcludeIconText(selector) {
// Get the text of the selector
let text = await selector.textContent();
// List of icons
const icons = await selector.locator('.material-symbols-outlined');
const iconCount = await icons.count();
// Remove the text of each icon from the text
for (let i = 0; i < iconCount; i++) {
await icons.nth(i).waitFor();
const iconText = await icons.nth(i).textContent();
text = text.replace(iconText, '');
}
// trim text for any spaces
return text.trim();
}
export { getTextExcludeIconText };
Loading…
Cancel
Save