Browse Source

feat(test): Added test for keyboard shortcuts

pull/4482/head
Muhammed Mustafa 2 years ago
parent
commit
d43f885948
  1. 2
      packages/nc-gui/components/tabs/auth/user-management/UsersModal.vue
  2. 6
      tests/playwright/pages/Dashboard/ExpandedForm/index.ts
  3. 16
      tests/playwright/pages/Dashboard/Grid/Column/index.ts
  4. 6
      tests/playwright/pages/Dashboard/Grid/index.ts
  5. 9
      tests/playwright/pages/Dashboard/Settings/Teams.ts
  6. 22
      tests/playwright/pages/Dashboard/TreeView.ts
  7. 12
      tests/playwright/pages/Dashboard/ViewSidebar/index.ts
  8. 8
      tests/playwright/pages/Dashboard/common/Cell/index.ts
  9. 102
      tests/playwright/tests/keyboardShortcuts.spec.ts

2
packages/nc-gui/components/tabs/auth/user-management/UsersModal.vue

@ -178,7 +178,7 @@ const emailField = (inputEl: typeof Input) => {
<a-alert class="mt-1" type="success" show-icon>
<template #message>
<div class="flex flex-row justify-between items-center py-1">
<div class="flex pl-2 text-green-700 text-xs">
<div class="flex pl-2 text-green-700 text-xs" data-testid="invite-modal-invitation-url">
{{ inviteUrl }}
</div>

6
tests/playwright/pages/Dashboard/ExpandedForm/index.ts

@ -93,9 +93,11 @@ export class ExpandedFormPage extends BasePage {
await this.rootPage.locator('[data-testid="grid-load-spinner"]').waitFor({ state: 'hidden' });
}
async verify({ header, url }: { header: string; url: string }) {
async verify({ header, url }: { header: string; url?: string }) {
await expect(this.get().locator(`.nc-expanded-form-header`).last()).toContainText(header);
await expect.poll(() => this.rootPage.url()).toContain(url);
if (url) {
await expect.poll(() => this.rootPage.url()).toContain(url);
}
}
async escape() {

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

@ -17,6 +17,14 @@ export class ColumnPageObject extends BasePage {
return this.rootPage.locator('form[data-testid="add-or-edit-column"]');
}
private getColumnHeader(title: string) {
return this.grid.get().locator(`th[data-title="${title}"]`);
}
async clickColumnHeader({ title }: { title: string }) {
await this.getColumnHeader(title).click();
}
async create({
title,
type = 'SingleLineText',
@ -141,7 +149,7 @@ export class ColumnPageObject extends BasePage {
}
async delete({ title }: { title: string }) {
await this.grid.get().locator(`th[data-title="${title}"] >> svg.ant-dropdown-trigger`).click();
await this.getColumnHeader(title).locator('svg.ant-dropdown-trigger').click();
// await this.rootPage.locator('li[role="menuitem"]:has-text("Delete")').waitFor();
await this.rootPage.locator('li[role="menuitem"]:has-text("Delete")').click();
@ -162,7 +170,7 @@ export class ColumnPageObject extends BasePage {
formula?: string;
format?: string;
}) {
await this.grid.get().locator(`th[data-title="${title}"] .nc-ui-dt-dropdown`).click();
await this.getColumnHeader(title).locator('.nc-ui-dt-dropdown').click();
await this.rootPage.locator('li[role="menuitem"]:has-text("Edit")').click();
await this.get().waitFor({ state: 'visible' });
@ -201,9 +209,9 @@ export class ColumnPageObject extends BasePage {
async verify({ title, isVisible = true }: { title: string; isVisible?: boolean }) {
if (!isVisible) {
return await expect(await this.rootPage.locator(`th[data-title="${title}"]`)).not.toBeVisible();
return await expect(this.getColumnHeader(title)).not.toBeVisible();
}
await await expect(this.rootPage.locator(`th[data-title="${title}"]`)).toContainText(title);
await expect(this.getColumnHeader(title)).toContainText(title);
}
async verifyRoleAccess(param: { role: string }) {

6
tests/playwright/pages/Dashboard/Grid/index.ts

@ -111,7 +111,11 @@ export class GridPage extends BasePage {
await this.waitForResponse({
uiAction: clickOnColumnHeaderToSave,
requestUrlPathToMatch: 'api/v1/db/data/noco',
httpMethodsToMatch: ['PATCH'],
httpMethodsToMatch: [
'PATCH',
// since edit row on an empty row will emit POST request
'POST',
],
responseJsonMatcher: resJson => resJson?.[columnHeader] === value,
});
} else {

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

@ -28,10 +28,11 @@ export class TeamsPage extends BasePage {
return this.rootPage.getByTestId('nc-share-base-sub-modal');
}
async invite({ email, role }: { email: string; role: string }) {
async invite({ email, role, skipOpeningModal }: { email: string; role: string; skipOpeningModal?: boolean }) {
email = this.prefixEmail(email);
await this.inviteTeamBtn.click();
if (!skipOpeningModal) await this.inviteTeamBtn.click();
await this.inviteTeamModal.locator(`input[placeholder="E-mail"]`).fill(email);
await this.inviteTeamModal.locator(`.nc-user-roles`).click();
const userRoleModal = this.rootPage.locator(`.nc-dropdown-user-role`);
@ -78,6 +79,10 @@ export class TeamsPage extends BasePage {
return await this.getSharedBaseSubModal().locator(`.nc-url:visible`).textContent();
}
async getInvitationUrl() {
return await this.rootPage.getByTestId('invite-modal-invitation-url').textContent();
}
async sharedBaseActions({ action }: { action: string }) {
const actionMenu = ['reload', 'copy url', 'open tab', 'copy embed code'];
const index = actionMenu.indexOf(action);

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

@ -20,6 +20,18 @@ export class TreeViewPage extends BasePage {
return this.dashboard.get().locator('.nc-treeview-container');
}
async isVisible() {
return await this.get().isVisible();
}
async verifyVisibility({ isVisible }: { isVisible: boolean }) {
if (isVisible) {
await expect(this.get()).toBeVisible();
} else {
await expect(this.get()).not.toBeVisible();
}
}
async focusTable({ title }: { title: string }) {
await this.get().locator(`.nc-project-tree-tbl-${title}`).focus();
}
@ -43,8 +55,8 @@ export class TreeViewPage extends BasePage {
await this.dashboard.waitForTabRender({ title, mode });
}
async createTable({ title }: { title: string }) {
await this.get().locator('.nc-add-new-table').click();
async createTable({ title, skipOpeningModal }: { title: string; skipOpeningModal?: boolean }) {
if (!skipOpeningModal) await this.get().locator('.nc-add-new-table').click();
await this.dashboard.get().locator('.nc-modal-table-create').locator('.ant-modal-body').waitFor();
@ -63,13 +75,13 @@ export class TreeViewPage extends BasePage {
async verifyTable({ title, index, exists = true }: { title: string; index?: number; exists?: boolean }) {
if (exists) {
await expect(this.get().locator(`.nc-project-tree-tbl-${title}`)).toBeVisible();
await expect(this.get().getByTestId(`tree-view-table-${title}`)).toHaveCount(1);
if (index) {
await expect(await this.get().locator('.nc-tbl-title').nth(index)).toHaveText(title);
await expect(this.get().locator('.nc-tbl-title').nth(index)).toHaveText(title);
}
} else {
await expect(this.get().locator(`.nc-project-tree-tbl-${title}`)).toHaveCount(0);
await expect(this.get().getByTestId(`tree-view-table-${title}`)).toHaveCount(0);
}
}

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

@ -23,6 +23,18 @@ export class ViewSidebarPage extends BasePage {
return this.dashboard.get().locator('.nc-view-sidebar');
}
async isVisible() {
return await this.get().isVisible();
}
async verifyVisibility({ isVisible }: { isVisible: boolean }) {
if (isVisible) {
await expect(this.get()).toBeVisible();
} else {
await expect(this.get()).not.toBeVisible();
}
}
private async createView({ title, locator }: { title: string; locator: Locator }) {
await locator.click();
await this.rootPage.locator('input[id="form_item_title"]:visible').fill(title);

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

@ -60,6 +60,14 @@ export class CellPageObject extends BasePage {
await this.get({ index, columnHeader }).locator('.nc-action-icon.nc-plus').click();
}
async verifyCellActiveSelected({ index, columnHeader }: { index: number; columnHeader: string }) {
await expect(this.get({ index, columnHeader })).toHaveClass(/active/);
}
async verifyCellEditable({ index, columnHeader }: { index: number; columnHeader: string }) {
await this.get({ index, columnHeader }).isEditable();
}
async verify({ index, columnHeader, value }: { index: number; columnHeader: string; value: string | string[] }) {
const _verify = async text => {
await expect

102
tests/playwright/tests/keyboardShortcuts.spec.ts

@ -0,0 +1,102 @@
import { expect, test } from '@playwright/test';
import { DashboardPage } from '../pages/Dashboard';
import { GridPage } from '../pages/Dashboard/Grid';
import setup from '../setup';
test.describe.only('Verify shortcuts', () => {
let dashboard: DashboardPage, grid: GridPage;
let context: any;
test.beforeEach(async ({ page }) => {
context = await setup({ page });
dashboard = new DashboardPage(page, context.project);
grid = dashboard.grid;
});
test('Verify shortcuts', async ({ page }) => {
await dashboard.treeView.openTable({ title: 'Country' });
// create new table
await page.keyboard.press('Alt+t');
await dashboard.treeView.createTable({ title: 'New Table', skipOpeningModal: true });
await dashboard.treeView.verifyTable({ title: 'New Table' });
// create new row
await grid.column.clickColumnHeader({ title: 'Title' });
await page.waitForTimeout(2000);
await page.keyboard.press('Alt+r');
await grid.editRow({ index: 0, value: 'New Row' });
await grid.verifyRowCount({ count: 1 });
// create new column
await page.keyboard.press('Alt+c');
await grid.column.fillTitle({ title: 'New Column' });
await grid.column.save();
await grid.column.verify({ title: 'New Column' });
// fullscreen
await page.keyboard.press('Alt+f');
await dashboard.treeView.verifyVisibility({
isVisible: false,
});
await dashboard.viewSidebar.verifyVisibility({
isVisible: false,
});
await page.keyboard.press('Alt+f');
await dashboard.treeView.verifyVisibility({
isVisible: true,
});
await dashboard.viewSidebar.verifyVisibility({
isVisible: true,
});
// invite team member
await page.keyboard.press('Alt+i');
await dashboard.settings.teams.invite({
email: 'new@example.com',
role: 'editor',
skipOpeningModal: true,
});
const url = await dashboard.settings.teams.getInvitationUrl();
// await dashboard.settings.teams.closeInvite();
expect(url).toContain('signup');
await page.waitForTimeout(1000);
await dashboard.settings.teams.closeInvite();
// Cmd + Right arrow
await dashboard.treeView.openTable({ title: 'Country' });
await grid.cell.click({ index: 0, columnHeader: 'Country' });
await page.keyboard.press('Meta+ArrowRight');
await grid.cell.verifyCellActiveSelected({ index: 0, columnHeader: 'City List' });
// Cmd + Right arrow
await page.keyboard.press('Meta+ArrowLeft');
await grid.cell.verifyCellActiveSelected({ index: 0, columnHeader: 'Country' });
// Cmd + up arrow
await grid.cell.click({ index: 24, columnHeader: 'Country' });
await page.keyboard.press('Meta+ArrowUp');
await grid.cell.verifyCellActiveSelected({ index: 0, columnHeader: 'Country' });
// Cmd + down arrow
await page.keyboard.press('Meta+ArrowDown');
await grid.cell.verifyCellActiveSelected({ index: 24, columnHeader: 'Country' });
// Enter to edit and Esc to cancel
await grid.cell.click({ index: 0, columnHeader: 'Country' });
await page.keyboard.press('Enter');
await page.keyboard.type('New');
await page.keyboard.press('Escape');
await grid.cell.verify({ index: 0, columnHeader: 'Country', value: 'AfghanistanNew' });
// Space to open expanded row and Meta + Space to save
await grid.cell.click({ index: 1, columnHeader: 'Country' });
await page.keyboard.press('Space');
await dashboard.expandedForm.verify({
header: 'Algeria',
});
await dashboard.expandedForm.fillField({ columnTitle: 'Country', value: 'NewAlgeria' });
await page.keyboard.press('Meta+Enter');
await page.waitForTimeout(2000);
await grid.cell.verify({ index: 1, columnHeader: 'Country', value: 'NewAlgeria' });
});
});
Loading…
Cancel
Save