Files
nocodb/packages/noco-docs/versioned_docs/version-0.109.7/050.engineering/050.playwright.md
Pranav C 33ee9bfa62 feat: Improved UI (#6222)
* feat: Improved ui (#6156)

* refactor: revert

Signed-off-by: Pranav C <pranavxc@gmail.com>

feat: shared base

Signed-off-by: Pranav C <pranavxc@gmail.com>

fix: remove duplicate import statement

Signed-off-by: Pranav C <pranavxc@gmail.com>

fix: disable starred & license menu

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: fix airtable wait issue

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: enable mysql in ci

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: fix checkbox order for sqlite

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: disable quick tests

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: fix dbType env variable for CI

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: workspace API access error fix

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: enable SQLite CI CD

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: use DB_TYPE env variable

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: enable SQLite UT

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: isHub cleanup

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: add check for EE Timezone spec

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

chore: cleanup

Signed-off-by: Pranav C <pranavxc@gmail.com>

chore: cleanup

Signed-off-by: Pranav C <pranavxc@gmail.com>

test: EE check fix

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

chore: test correction

Signed-off-by: Pranav C <pranavxc@gmail.com>

chore: sync latest changes

Signed-off-by: Pranav C <pranavxc@gmail.com>

test: set EE=false

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

test: set NC Edition to community in workflow file

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

chore: update sdk build command

Signed-off-by: Pranav C <pranavxc@gmail.com>

refactor: i18n and other changes

Signed-off-by: Pranav C <pranavxc@gmail.com>

feat: new ui

Signed-off-by: Pranav C <pranavxc@gmail.com>

* chore: sync tests

Signed-off-by: Pranav C <pranavxc@gmail.com>

* chore: lint

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: shared view/base related bugs

Signed-off-by: Pranav C <pranavxc@gmail.com>

* test: checkbox verification sort order fix

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: fix sqlite reset

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: enable selfhosted runners

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* docs: table ops (draft)

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* Docs: screenshots for table-operations.md

* refactor: introduce missing buttons

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: get all fields

Signed-off-by: Pranav C <pranavxc@gmail.com>

* test: UT fix- new data API response

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: EE is false

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: webhook lookup as string in CE

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* fix: include created_at and updated_at

Signed-off-by: Pranav C <pranavxc@gmail.com>

* test: fix UT newDataAPI response for PG

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* fix: separate api for webhook related plugins

Signed-off-by: Pranav C <pranavxc@gmail.com>

* test: msyql filter corrections

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: mysql group by test corrections

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: fix datatype for rating field in groupby spec for pg

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: kanban datatype correction

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: column edit for mysql- rating field

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: misc fixes

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: enable 4 workers

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: enable 2 workers per shard only

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* docs: table CRUD

* Rename table-operations.md to table-crud.md

* Create column-crud.md

* docs: row CRUD

* Rename row.md to row-crud.md

* docs: project crud

* docs: toolbar (skeleton)

* refactor: single page UI and bug fixes

Signed-off-by: Pranav C <pranavxc@gmail.com>

* chore: sync tests playwright

Signed-off-by: Pranav C <pranavxc@gmail.com>

* chore: add missing dependency

Signed-off-by: Pranav C <pranavxc@gmail.com>

* feat: single page ui, test corrections

Signed-off-by: Pranav C <pranavxc@gmail.com>

* chore: tests

Signed-off-by: Pranav C <pranavxc@gmail.com>

* test: project rename test correction

Signed-off-by: Pranav C <pranavxc@gmail.com>

* chore: remove only

Signed-off-by: Pranav C <pranavxc@gmail.com>

* test: remove wrong import statement

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: delete option not visible in project context menu

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: move ws access within isEE()

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: fix groupby

* test: groupby fix

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* docs: signup & landing page

* docs: project crud

* docs: project-crud misc

* docs: toolbar fields

* docs: toolbar / filters

* docs: toolbar / group by

* docs: toolbar / sort

* docs: toolbar / row height

* docs: filters additional options

* docs: file re-order

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* docs: add links to column types

* docs: code snippets

* docs: links

* docs: lookup

* docs: rollup

* docs: formula

* docs: primary key

* docs: display value

* docs: development setup

* docs: swagger

* fix(nc-gui): encodeURIComponent for row id

- closes: #6202

* docs: language

* docs: expanded record

* docs: import airtable

* docs: airtable

* docs: webhook

* docs: revert file rename

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* docs: account settings

* docs: audit

* docs: meta management

* docs: project settings

* docs: shared base

* docs: shared view

* docs: meta sync

* docs: team-auth

* docs: views

* docs: fix URL

* docs: URL corrections

* fix:  shared base, view related bugs

Signed-off-by: Pranav C <pranavxc@gmail.com>

* test: EE check for WSaccess

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* test: exclude EE tests

Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>

* fix: missing project delete

closes #6215

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: merge existing project meta  if found

closes #6216

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: merge existing project meta  if found

closes #6216

Signed-off-by: Pranav C <pranavxc@gmail.com>

---------

Signed-off-by: Pranav C <pranavxc@gmail.com>
Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>
Co-authored-by: Raju Udava <86527202+dstala@users.noreply.github.com>
Co-authored-by: DarkPhoenix2704 <anbarasun123@gmail.com>
Co-authored-by: Wing-Kam Wong <wingkwong.code@gmail.com>

* refactor: docs and other bug fixes

Signed-off-by: Pranav C <pranavxc@gmail.com>

* feat: populate default project on super admin signup

Signed-off-by: Pranav C <pranavxc@gmail.com>

* fix: include created project details in signup response if avail, missing Dockerfile

Signed-off-by: Pranav C <pranavxc@gmail.com>

* chore: use custom function for resolving ts path aliases

Signed-off-by: Pranav C <pranavxc@gmail.com>

* chore: add missing generate script

Signed-off-by: Pranav C <pranavxc@gmail.com>

* chore: webpack build correction - ts path resolve

Signed-off-by: Pranav C <pranavxc@gmail.com>

---------

Signed-off-by: Pranav C <pranavxc@gmail.com>
Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com>
Co-authored-by: mertmit <mertmit99@gmail.com>
Co-authored-by: Raju Udava <86527202+dstala@users.noreply.github.com>
Co-authored-by: DarkPhoenix2704 <anbarasun123@gmail.com>
Co-authored-by: Wing-Kam Wong <wingkwong.code@gmail.com>
2023-08-24 02:58:19 +05:30

7.5 KiB

title, description
title description
Playwright E2E Testing Overview to playwright based e2e tests

How to run tests

All the tests reside in tests/playwright folder.

Make sure to install the dependencies(in the playwright folder):

npm install
npx playwright install chromium --with-deps

Run Test Server

Start the backend test server (in packages/nocodb folder):

npm run watch:run:playwright

Start the frontend test server (in packages/nc-gui folder):

NUXT_PAGE_TRANSITION_DISABLE=true npm run dev

Running all tests

For selecting db type, rename .env.example to .env and set E2E_DEV_DB_TYPE to sqlite(default), mysql or pg.

headless mode(without opening browser):

npm run test

with browser:

npm run test:debug

For setting up mysql(sakila):

docker-compose -f ./tests/playwright/scripts/docker-compose-mysql-playwright.yml  up -d

For setting up postgres(sakila):

docker-compose -f ./tests/playwright/scripts/docker-compose-playwright-pg.yml 

Running individual tests

Add .only to the test you want to run:

test.only('should login', async ({ page }) => {
  // ...
})
npm run test

Concepts

Independent tests

  • All tests are independent of each other.
  • Each test starts with a fresh project with a fresh sakila database(option to not use sakila db is also there).
  • Each test creates a new user(email as user@nocodb.com) and logs in with that user to the dashboard.

Caveats:

  • Some stuffs are shared i.e, users, plugins etc. So be catious while writing tests touching that. A fix for this is in the works.
  • In test, we prefix email and project with the test id, which will be deleted after the test is done.

What to test

  • UI verification. This includes verifying the state of the UI element, i.e if the element is visible, if the element has a particular text etc.
  • Test should verify all user flow. A test has a default timeout of 60 seconds. If a test is taking more than 60 seconds, it is a sign that the test should be broken down into smaller tests.
  • Test should also verify all the side effects the feature(i.e. On adding a new column type, should verify column deletion as well) will have, and also error cases.
  • Test name should be descriptive. It should be easy to understand what the test is doing by just reading the test name.

Playwright

  • Playwright is a nodejs library for automating chromium, firefox and webkit.
  • For each test, a new browser context is created. This means that each test runs in a new incognito window.
  • For assertion always use expect from @playwright/test library. This library provides a lot of useful assertions, which also has retry logic built in.

Page Objects

  • Page objects are used to abstract over the components/page. This makes the tests more readable and maintainable.
  • All page objects are in tests/playwright/pages folder.
  • All the test related code should be in page objects.
  • Methods should be as thin as possible and its better to have multiple methods than one big method, which improves reusability.

The methods of a page object can be classified into 2 categories:

  • Actions: Performs an UI actions like click, type, select etc. Is also responsible for waiting for the element to be ready and the action to be performed. This included waiting for API calls to complete.
  • Assertions: Asserts the state of the UI element, i.e if the element is visible, if the element has a particular text etc. Use expect from @playwright/test and if not use expect.poll to wait for the assertion to pass.

Writing a test

Let's write a test for testing filter functionality.

For simplicity, we will have DashboardPage implemented, which will have all the methods related to dashboard page and also its child components like Grid, etc.

Create a test suite

Create a new file filter.spec.ts in tests/playwright/tests folder and use setup method to create a new project and user.

import { test, expect } from '@playwright/test';
import setup, { NcContext } from '../setup';

test.describe('Filter', () => {
  let context: NcContext;

  test.beforeEach(async ({ page }) => {
    context = await setup({ page });
  })

  test('should filter', async ({ page }) => {
    // ...
  });
});

Create a page object

Since filter is UI wise scoped to a Toolbar , we will add filter page object to ToolbarPage page object.

export class ToolbarPage extends BasePage {
  readonly parent: GridPage | GalleryPage | FormPage | KanbanPage;
  readonly filter: ToolbarFilterPage;

  constructor(parent: GridPage | GalleryPage | FormPage | KanbanPage) {
    super(parent.rootPage);
    this.parent = parent;
    this.filter = new ToolbarFilterPage(this);
  }
}

We will create ToolbarFilterPage page object, which will have all the methods related to filter.

export class ToolbarFilterPage extends BasePage {
  readonly toolbar: ToolbarPage;

  constructor(toolbar: ToolbarPage) {
    super(toolbar.rootPage);
    this.toolbar = toolbar;
  }
}

Here BasePage is an abstract class, which used to enforce structure for all page objects. Thus all page object should inherit BasePage.

  • Helper methods like waitForResponse and getClipboardText (this can be access on any page object, with this.waitForResponse)
  • Provides structure for page objects, enforces all Page objects to have rootPage property, which is the page object created in the test setup.
  • Enforces all pages to have a get method which will return the locator of the main container of that page, hence we can have focused dom selection, i.e.
// This will only select the button inside the container of the concerned page
await this.get().querySelector('button').count();

Writing an action method

This a method which will reset/clear all the filters. Since this is an action method, it will also wait for the delete filter API to return. Ignoring this API call will cause flakiness in the test, down the line.

async resetFilter() {
  await this.waitForResponse({
    uiAction: () => this.get().locator('.nc-filter-item-remove-btn').click(),
    httpMethodsToMatch: ['DELETE'],
    requestUrlPathToMatch: '/api/v1/db/meta/filters/',
  });
}

Writing an assertion/verification method

Here we use expect from @playwright/test library, which has retry logic built in.

import { expect } from '@playwright/test';

async verifyFilter({ title }: { title: string }) {
  await expect(
    this.get().locator(`[data-testid="nc-fields-menu-${title}"]`).locator('input[type="checkbox"]')
  ).toBeChecked();
}

Tips to avoid flakiness

  • If an UI action, causes an API call or the UI state change, then wait for that API call to complete or the UI state to change.
  • What to wait out can be situation specific, but in general, is best to wait for the final state to be reached, i.e. in the case of creating filter, while it seems like waiting for the filter API to complete is enough, but after its return the table rows are reloaded and the UI state changes, so its better to wait for the table rows to be reloaded.

Accessing playwright report in the CI

  • Open Summary tab in the CI workflow in github actions.
  • Scroll down to Artifacts section.
  • Access reports which suffixed with the db type and shard number(corresponding to the CI workerflow name). i.e playwright-report-mysql-2 is for playwright-mysql-2 workflow.
  • Download it and run npm install -D @playwright/test && npx playwright show-report ./ inside the downloaded folder.